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.
package/dist/cli/index.js CHANGED
@@ -5191,6 +5191,11 @@ function parseDrawingPercent(value) {
5191
5191
  }
5192
5192
  return clampUnitInterval(parsed / 1e5);
5193
5193
  }
5194
+ function scrgbLinearToSrgb8(linear) {
5195
+ const l = Math.min(1, Math.max(0, linear));
5196
+ const companded = l <= 31308e-7 ? 12.92 * l : 1.055 * l ** (1 / 2.4) - 0.055;
5197
+ return Math.min(255, Math.max(0, Math.round(companded * 255)));
5198
+ }
5194
5199
  function toHex(value) {
5195
5200
  return Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
5196
5201
  }
@@ -6558,6 +6563,21 @@ function cloneXmlObject(value) {
6558
6563
 
6559
6564
  // src/core/utils/presentation-collections.ts
6560
6565
  var SECTION_EXTENSION_URI = "{521415D9-36F7-43E2-AB2F-B90AF26B5E84}";
6566
+ function remapReferenceList(references, mapping, removed) {
6567
+ const result = [];
6568
+ for (const reference of references) {
6569
+ const mapped = mapping.get(reference);
6570
+ if (mapped !== void 0) {
6571
+ result.push(mapped);
6572
+ continue;
6573
+ }
6574
+ if (removed.has(reference)) {
6575
+ continue;
6576
+ }
6577
+ result.push(reference);
6578
+ }
6579
+ return result;
6580
+ }
6561
6581
  function localName2(key) {
6562
6582
  return key.split(":").pop() ?? key;
6563
6583
  }
@@ -6624,7 +6644,7 @@ function updateCustomShow(show, existing) {
6624
6644
  replaceChildren(node, "sldLst", slideList, "p:sldLst");
6625
6645
  return node;
6626
6646
  }
6627
- function applyCustomShows(presentation, shows, lookup) {
6647
+ function applyCustomShows(presentation, shows, lookup, remap) {
6628
6648
  if (shows === void 0) {
6629
6649
  return;
6630
6650
  }
@@ -6638,14 +6658,18 @@ function applyCustomShows(presentation, shows, lookup) {
6638
6658
  const oldList = key ? presentation[key] : void 0;
6639
6659
  const list = cloneXmlObject(oldList) ?? {};
6640
6660
  const oldShows = lookup.getChildrenArrayByLocalName(oldList, "custShow");
6641
- const updated = shows.map(
6642
- (show) => updateCustomShow(
6643
- show,
6661
+ const updated = shows.map((show) => {
6662
+ const effective = remap && remap.changed ? {
6663
+ ...show,
6664
+ slideRIds: remapReferenceList(show.slideRIds, remap.rIdByOldRId, remap.removedRIds)
6665
+ } : show;
6666
+ return updateCustomShow(
6667
+ effective,
6644
6668
  oldShows.find(
6645
6669
  (node) => String(node[attributeKey(node, "id") ?? ""]) === show.id || String(node[attributeKey(node, "name") ?? ""]) === show.name
6646
6670
  )
6647
- )
6648
- );
6671
+ );
6672
+ });
6649
6673
  replaceChildren(list, "custShow", updated, "p:custShow");
6650
6674
  presentation[key ?? "p:custShowLst"] = list;
6651
6675
  }
@@ -6694,7 +6718,7 @@ function updateSection(section) {
6694
6718
  }
6695
6719
  return node;
6696
6720
  }
6697
- function applySections(presentation, sections, lookup) {
6721
+ function applySections(presentation, sections, lookup, remap) {
6698
6722
  if (sections === void 0) {
6699
6723
  return;
6700
6724
  }
@@ -6716,7 +6740,15 @@ function applySections(presentation, sections, lookup) {
6716
6740
  location = { parent: ext, key: "p14:sectionLst", list: ext["p14:sectionLst"] };
6717
6741
  }
6718
6742
  const list = cloneXmlObject(location.list) ?? {};
6719
- replaceChildren(list, "section", sections.map(updateSection), "p14:section");
6743
+ const effectiveSections = remap && remap.changed ? sections.map((section) => ({
6744
+ ...section,
6745
+ slideIds: remapReferenceList(
6746
+ section.slideIds,
6747
+ remap.sldIdByOldSldId,
6748
+ remap.removedSldIds
6749
+ )
6750
+ })) : sections;
6751
+ replaceChildren(list, "section", effectiveSections.map(updateSection), "p14:section");
6720
6752
  location.parent[location.key] = list;
6721
6753
  }
6722
6754
 
@@ -7253,36 +7285,200 @@ async function fetchUrlToBytes(url, options = {}) {
7253
7285
  }
7254
7286
  }
7255
7287
 
7288
+ // src/core/utils/inkml-trace-decode.ts
7289
+ function resolveChannelOrder(root) {
7290
+ const traceFormat = findFirstByLocalName(root, "traceFormat");
7291
+ if (!traceFormat) {
7292
+ return ["X", "Y"];
7293
+ }
7294
+ const channels = ensureArray(nsGet(traceFormat, "channel"));
7295
+ const names = channels.map(
7296
+ (channel) => String(nsAttr(channel, "name") ?? "").trim().toUpperCase()
7297
+ ).filter((name) => name.length > 0);
7298
+ return names.length > 0 ? names : ["X", "Y"];
7299
+ }
7300
+ function decodeTracePoints(text2, channelOrder) {
7301
+ const points3 = [];
7302
+ const modes = channelOrder.map(() => "explicit");
7303
+ const lastValue = channelOrder.map(() => 0);
7304
+ const lastVelocity = channelOrder.map(() => 0);
7305
+ for (const rawPoint of text2.split(",")) {
7306
+ const tokens = rawPoint.trim().split(/\s+/u).filter((token2) => token2.length > 0);
7307
+ if (tokens.length === 0) {
7308
+ continue;
7309
+ }
7310
+ const decoded = [];
7311
+ for (let i = 0; i < tokens.length && i < channelOrder.length; i++) {
7312
+ const parsed = parseValueToken(tokens[i], modes[i]);
7313
+ if (parsed === void 0) {
7314
+ decoded.push(lastValue[i]);
7315
+ continue;
7316
+ }
7317
+ modes[i] = parsed.mode;
7318
+ const value = applyDiffMode(parsed, i, lastValue, lastVelocity);
7319
+ decoded.push(value);
7320
+ }
7321
+ if (decoded.length >= 2) {
7322
+ points3.push(decoded);
7323
+ }
7324
+ }
7325
+ return points3;
7326
+ }
7327
+ function parseValueToken(token2, currentMode) {
7328
+ let mode = currentMode;
7329
+ let body = token2;
7330
+ const prefix = token2[0];
7331
+ if (prefix === "!") {
7332
+ mode = "explicit";
7333
+ body = token2.slice(1);
7334
+ } else if (prefix === "'") {
7335
+ mode = "single";
7336
+ body = token2.slice(1);
7337
+ } else if (prefix === '"') {
7338
+ mode = "double";
7339
+ body = token2.slice(1);
7340
+ }
7341
+ if (body.length === 0) {
7342
+ return void 0;
7343
+ }
7344
+ const value = Number(body);
7345
+ return Number.isFinite(value) ? { value, mode } : void 0;
7346
+ }
7347
+ function applyDiffMode(parsed, index, lastValue, lastVelocity) {
7348
+ if (parsed.mode === "single") {
7349
+ lastVelocity[index] = parsed.value;
7350
+ lastValue[index] += parsed.value;
7351
+ } else if (parsed.mode === "double") {
7352
+ lastVelocity[index] += parsed.value;
7353
+ lastValue[index] += lastVelocity[index];
7354
+ } else {
7355
+ lastValue[index] = parsed.value;
7356
+ lastVelocity[index] = 0;
7357
+ }
7358
+ return lastValue[index];
7359
+ }
7360
+ function pointsToSvgPath(points3, channelOrder) {
7361
+ const xi = channelOrder.indexOf("X");
7362
+ const yi = channelOrder.indexOf("Y");
7363
+ const xIndex = xi >= 0 ? xi : 0;
7364
+ const yIndex = yi >= 0 ? yi : 1;
7365
+ const segments = [];
7366
+ for (const point of points3) {
7367
+ const x = point[xIndex];
7368
+ const y = point[yIndex];
7369
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
7370
+ continue;
7371
+ }
7372
+ segments.push(`${segments.length === 0 ? "M" : "L"} ${x} ${y}`);
7373
+ }
7374
+ return segments.join(" ");
7375
+ }
7376
+ function pointsToPressures(points3, channelOrder) {
7377
+ const fIndex = channelOrder.indexOf("F");
7378
+ if (fIndex < 0) {
7379
+ return [];
7380
+ }
7381
+ const pressures = [];
7382
+ for (const point of points3) {
7383
+ const raw = point[fIndex];
7384
+ if (Number.isFinite(raw)) {
7385
+ const normalised = raw > 1 ? raw / 32767 : raw;
7386
+ pressures.push(Math.max(0, Math.min(1, normalised)));
7387
+ }
7388
+ }
7389
+ return pressures;
7390
+ }
7391
+ function nsGet(obj, localName21) {
7392
+ if (localName21 in obj) {
7393
+ return obj[localName21];
7394
+ }
7395
+ for (const key of Object.keys(obj)) {
7396
+ if (localNameOf(key) === localName21 && !key.startsWith("@_")) {
7397
+ return obj[key];
7398
+ }
7399
+ }
7400
+ return void 0;
7401
+ }
7402
+ function nsAttr(obj, localName21) {
7403
+ const direct = obj[`@_${localName21}`];
7404
+ if (direct !== void 0) {
7405
+ return direct;
7406
+ }
7407
+ for (const key of Object.keys(obj)) {
7408
+ if (key.startsWith("@_") && localNameOf(key.slice(2)) === localName21) {
7409
+ return obj[key];
7410
+ }
7411
+ }
7412
+ return void 0;
7413
+ }
7414
+ function localNameOf(key) {
7415
+ const colon = key.indexOf(":");
7416
+ return colon >= 0 ? key.slice(colon + 1) : key;
7417
+ }
7418
+ function findFirstByLocalName(node, localName21) {
7419
+ const direct = nsGet(node, localName21);
7420
+ if (direct && typeof direct === "object") {
7421
+ return Array.isArray(direct) ? direct[0] : direct;
7422
+ }
7423
+ for (const key of Object.keys(node)) {
7424
+ if (key.startsWith("@_") || key === "#text") {
7425
+ continue;
7426
+ }
7427
+ for (const child20 of ensureArray(node[key])) {
7428
+ if (typeof child20 !== "object") {
7429
+ continue;
7430
+ }
7431
+ const found = findFirstByLocalName(child20, localName21);
7432
+ if (found) {
7433
+ return found;
7434
+ }
7435
+ }
7436
+ }
7437
+ return void 0;
7438
+ }
7439
+ function ensureArray(value) {
7440
+ if (value === void 0 || value === null) {
7441
+ return [];
7442
+ }
7443
+ return Array.isArray(value) ? value : [value];
7444
+ }
7445
+
7256
7446
  // src/core/utils/inkml-content-part.ts
7257
7447
  var INKML_NAMESPACE = "http://www.w3.org/2003/InkML";
7258
7448
  var METADATA_NAMESPACE = "https://pptx-viewer.dev/inkml/metadata";
7259
7449
  function parseInkMlContent(data) {
7260
- const root = data["ink:ink"] ?? data["ink"];
7450
+ const root = nsGet(data, "ink") ?? data["ink"];
7261
7451
  if (!root) {
7262
7452
  return { strokes: [], rawXml: data };
7263
7453
  }
7264
7454
  const brushes = /* @__PURE__ */ new Map();
7265
- for (const brush of ensureArray(root["ink:brush"] ?? root["brush"])) {
7266
- const properties = ensureArray(brush["ink:brushProperty"] ?? brush["brushProperty"]);
7455
+ for (const brush of ensureArray(nsGet(root, "brush"))) {
7456
+ const properties = ensureArray(nsGet(brush, "brushProperty"));
7267
7457
  const valueByName = new Map(
7268
- properties.map((property) => [String(property["@_name"] ?? ""), property["@_value"]])
7458
+ properties.map((property) => [
7459
+ String(nsAttr(property, "name") ?? ""),
7460
+ nsAttr(property, "value")
7461
+ ])
7269
7462
  );
7270
- brushes.set(String(brush["@_id"] ?? ""), {
7463
+ brushes.set(String(nsAttr(brush, "id") ?? ""), {
7271
7464
  color: String(valueByName.get("color") ?? "#000000"),
7272
7465
  width: finiteNumber(valueByName.get("width"), 1),
7273
7466
  opacity: finiteNumber(valueByName.get("opacity"), 1)
7274
7467
  });
7275
7468
  }
7469
+ const channelOrder = resolveChannelOrder(root);
7276
7470
  const strokes = [];
7277
- for (const trace of ensureArray(root["ink:trace"] ?? root["trace"])) {
7471
+ for (const trace of ensureArray(nsGet(root, "trace"))) {
7278
7472
  const text2 = typeof trace === "string" ? trace : String(trace["#text"] ?? "").trim();
7279
- const path2 = typeof trace === "string" ? text2 : String(trace["@_pva:path"] ?? "").trim() || text2;
7473
+ const authored = typeof trace === "string" ? "" : String(nsAttr(trace, "path") ?? "").trim();
7474
+ const points3 = authored ? [] : decodeTracePoints(text2, channelOrder);
7475
+ const path2 = authored || pointsToSvgPath(points3, channelOrder);
7280
7476
  if (!path2) {
7281
7477
  continue;
7282
7478
  }
7283
- const brushRef = typeof trace === "string" ? "" : String(trace["@_brushRef"] ?? "").replace("#", "");
7479
+ const brushRef = typeof trace === "string" ? "" : String(nsAttr(trace, "brushRef") ?? "").replace("#", "");
7284
7480
  const brush = brushes.get(brushRef) ?? { color: "#000000", width: 1, opacity: 1 };
7285
- const pressures = tracePressures(text2);
7481
+ const pressures = authored ? tracePressures(text2) : pointsToPressures(points3, channelOrder);
7286
7482
  strokes.push({ ...brush, path: path2, ...pressures.length > 0 ? { pressures } : {} });
7287
7483
  }
7288
7484
  return { strokes, rawXml: data };
@@ -7341,12 +7537,6 @@ function finiteNumber(value, fallback) {
7341
7537
  const parsed = Number(value);
7342
7538
  return Number.isFinite(parsed) ? parsed : fallback;
7343
7539
  }
7344
- function ensureArray(value) {
7345
- if (value === void 0 || value === null) {
7346
- return [];
7347
- }
7348
- return Array.isArray(value) ? value : [value];
7349
- }
7350
7540
 
7351
7541
  // src/core/utils/strip-parent-dir-segments.ts
7352
7542
  function stripParentDirSegments(path2) {
@@ -10553,6 +10743,122 @@ function applyNodeStylesToElements(elements, nodes) {
10553
10743
  });
10554
10744
  }
10555
10745
 
10746
+ // src/core/utils/smartart-pres-layout-vars.ts
10747
+ var CONTAINER_LOCAL_NAMES = /* @__PURE__ */ new Set(["presLayoutVars", "varLst"]);
10748
+ function localNameOf2(key) {
10749
+ const idx = key.indexOf(":");
10750
+ return idx >= 0 ? key.slice(idx + 1) : key;
10751
+ }
10752
+ function findVarsContainer(node) {
10753
+ if (!node || typeof node !== "object") {
10754
+ return void 0;
10755
+ }
10756
+ if (Array.isArray(node)) {
10757
+ for (const entry of node) {
10758
+ const found = findVarsContainer(entry);
10759
+ if (found) {
10760
+ return found;
10761
+ }
10762
+ }
10763
+ return void 0;
10764
+ }
10765
+ for (const [key, value] of Object.entries(node)) {
10766
+ if (key.startsWith("@_")) {
10767
+ continue;
10768
+ }
10769
+ if (CONTAINER_LOCAL_NAMES.has(localNameOf2(key))) {
10770
+ const container = Array.isArray(value) ? value[0] : value;
10771
+ if (container && typeof container === "object") {
10772
+ return container;
10773
+ }
10774
+ }
10775
+ const nested = findVarsContainer(value);
10776
+ if (nested) {
10777
+ return nested;
10778
+ }
10779
+ }
10780
+ return void 0;
10781
+ }
10782
+ function varValue(container, name) {
10783
+ for (const [key, value] of Object.entries(container)) {
10784
+ if (key.startsWith("@_") || localNameOf2(key) !== name) {
10785
+ continue;
10786
+ }
10787
+ const node = Array.isArray(value) ? value[0] : value;
10788
+ if (node && typeof node === "object") {
10789
+ const raw = node["@_val"];
10790
+ const str = String(raw ?? "").trim();
10791
+ return str.length > 0 ? str : void 0;
10792
+ }
10793
+ }
10794
+ return void 0;
10795
+ }
10796
+ function boolValue(container, name) {
10797
+ const raw = varValue(container, name);
10798
+ if (raw === void 0) {
10799
+ return void 0;
10800
+ }
10801
+ const lower = raw.toLowerCase();
10802
+ return lower === "1" || lower === "true" || lower === "on";
10803
+ }
10804
+ function intValue(container, name) {
10805
+ const raw = varValue(container, name);
10806
+ if (raw === void 0) {
10807
+ return void 0;
10808
+ }
10809
+ const parsed = Number.parseInt(raw, 10);
10810
+ return Number.isFinite(parsed) ? parsed : void 0;
10811
+ }
10812
+ var DIRECTIONS = /* @__PURE__ */ new Set(["norm", "rev"]);
10813
+ var HIER_BRANCHES = /* @__PURE__ */ new Set(["std", "init", "l", "r", "hang"]);
10814
+ function parseSmartArtPresLayoutVars(container) {
10815
+ if (!container) {
10816
+ return void 0;
10817
+ }
10818
+ const vars = findVarsContainer(container);
10819
+ if (!vars) {
10820
+ return void 0;
10821
+ }
10822
+ const result = {};
10823
+ const direction = varValue(vars, "dir");
10824
+ if (direction && DIRECTIONS.has(direction)) {
10825
+ result.direction = direction;
10826
+ }
10827
+ const hierBranch = varValue(vars, "hierBranch");
10828
+ if (hierBranch && HIER_BRANCHES.has(hierBranch)) {
10829
+ result.hierarchyBranch = hierBranch;
10830
+ }
10831
+ const orgChart = boolValue(vars, "orgChart");
10832
+ if (orgChart !== void 0) {
10833
+ result.orgChart = orgChart;
10834
+ }
10835
+ const chMax = intValue(vars, "chMax");
10836
+ if (chMax !== void 0) {
10837
+ result.childMax = chMax;
10838
+ }
10839
+ const chPref = intValue(vars, "chPref");
10840
+ if (chPref !== void 0) {
10841
+ result.childPreferred = chPref;
10842
+ }
10843
+ const bulletEnabled = boolValue(vars, "bulletEnabled");
10844
+ if (bulletEnabled !== void 0) {
10845
+ result.bulletEnabled = bulletEnabled;
10846
+ }
10847
+ const animLvl = varValue(vars, "animLvl");
10848
+ if (animLvl !== void 0) {
10849
+ result.animationLevel = animLvl;
10850
+ }
10851
+ const animOne = varValue(vars, "animOne");
10852
+ if (animOne !== void 0) {
10853
+ result.animateOne = animOne;
10854
+ }
10855
+ const resizeHandles = varValue(vars, "resizeHandles");
10856
+ if (resizeHandles !== void 0) {
10857
+ result.resizeHandles = resizeHandles;
10858
+ }
10859
+ return Object.keys(result).length > 0 ? result : void 0;
10860
+ }
10861
+
10556
10862
  // src/core/utils/smartart-decompose.ts
10557
10863
  function quickStyleStrokeScale(quickStyle) {
10558
10864
  if (!quickStyle?.effectIntensity) {
@@ -10658,15 +10964,27 @@ function decomposeSmartArt(smartArtData, containerBounds, themeColorMap, layoutD
10658
10964
  smartArtData.colorTransform?.fillColors
10659
10965
  );
10660
10966
  const layoutType = resolveEffectiveLayoutType(smartArtData);
10967
+ const layoutVars = smartArtData.presLayoutVars ?? parseSmartArtPresLayoutVars(smartArtData.layoutDefinition?.rawXml);
10968
+ const orderedNodes = layoutVars?.direction === "rev" ? [...nodes].reverse() : nodes;
10661
10969
  const namedLayout = smartArtData.layout;
10662
10970
  if (namedLayout) {
10663
- const namedResult = dispatchNamedLayout(namedLayout, nodes, containerBounds, effectiveThemeMap);
10971
+ const namedResult = dispatchNamedLayout(
10972
+ namedLayout,
10973
+ orderedNodes,
10974
+ containerBounds,
10975
+ effectiveThemeMap
10976
+ );
10664
10977
  if (namedResult) {
10665
- return applyNodeStylesToElements(namedResult, nodes);
10978
+ return applyNodeStylesToElements(namedResult, orderedNodes);
10666
10979
  }
10667
10980
  }
10668
- const algorithmic = dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap);
10669
- return algorithmic ? applyNodeStylesToElements(algorithmic, nodes) : algorithmic;
10981
+ const algorithmic = dispatchLayoutByType(
10982
+ layoutType,
10983
+ orderedNodes,
10984
+ containerBounds,
10985
+ effectiveThemeMap
10986
+ );
10987
+ return algorithmic ? applyNodeStylesToElements(algorithmic, orderedNodes) : algorithmic;
10670
10988
  }
10671
10989
  function dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap) {
10672
10990
  switch (layoutType) {
@@ -16884,6 +17202,19 @@ function xmlChild(node, key) {
16884
17202
  }
16885
17203
  return isXmlObject2(value) ? value : void 0;
16886
17204
  }
17205
+ function xmlChildren(node, key) {
17206
+ if (!isXmlObject2(node)) {
17207
+ return [];
17208
+ }
17209
+ const value = node[key];
17210
+ if (value === void 0 || value === null) {
17211
+ return [];
17212
+ }
17213
+ if (Array.isArray(value)) {
17214
+ return value.filter(isXmlObject2);
17215
+ }
17216
+ return isXmlObject2(value) ? [value] : [];
17217
+ }
16887
17218
  function xmlHasChild(node, key) {
16888
17219
  return isXmlObject2(node) && Object.hasOwn(node, key);
16889
17220
  }
@@ -16911,6 +17242,9 @@ function xmlPath(node, ...keys) {
16911
17242
  }
16912
17243
  return current;
16913
17244
  }
17245
+ function isXmlNode(value) {
17246
+ return isXmlObject2(value);
17247
+ }
16914
17248
 
16915
17249
  // src/core/utils/chart-bubble-options.ts
16916
17250
  var ORDER2 = [
@@ -16927,7 +17261,7 @@ var ORDER2 = [
16927
17261
  function findKey4(node, name, localName21) {
16928
17262
  return Object.keys(node).find((key) => localName21(key) === name);
16929
17263
  }
16930
- function boolValue(node) {
17264
+ function boolValue2(node) {
16931
17265
  if (!node) {
16932
17266
  return void 0;
16933
17267
  }
@@ -16943,7 +17277,7 @@ function parseBubbleChartOptions(container, localName21) {
16943
17277
  return key ? container[key] : void 0;
16944
17278
  };
16945
17279
  const options = {};
16946
- const bubble3D = boolValue(node("bubble3D"));
17280
+ const bubble3D = boolValue2(node("bubble3D"));
16947
17281
  if (bubble3D !== void 0) {
16948
17282
  options.bubble3D = bubble3D;
16949
17283
  }
@@ -16954,7 +17288,7 @@ function parseBubbleChartOptions(container, localName21) {
16954
17288
  options.bubbleScale = scale;
16955
17289
  }
16956
17290
  }
16957
- const showNegative = boolValue(node("showNegBubbles"));
17291
+ const showNegative = boolValue2(node("showNegBubbles"));
16958
17292
  if (showNegative !== void 0) {
16959
17293
  options.showNegativeBubbles = showNegative;
16960
17294
  }
@@ -17266,7 +17600,7 @@ var MEDIA_REFERENCE_NAMES = [
17266
17600
  "videoFile",
17267
17601
  "quickTimeFile"
17268
17602
  ];
17269
- function parseDrawingMediaReference(container) {
17603
+ function parseDrawingMediaReference(container, externalRelIds) {
17270
17604
  if (!container) {
17271
17605
  return void 0;
17272
17606
  }
@@ -17275,11 +17609,17 @@ function parseDrawingMediaReference(container) {
17275
17609
  if (!node) {
17276
17610
  continue;
17277
17611
  }
17612
+ const linkId = String(attribute2(node, "link") ?? "").trim() || void 0;
17613
+ const embedId = String(attribute2(node, "embed") ?? "").trim() || void 0;
17278
17614
  return {
17279
17615
  kind,
17280
17616
  mediaType: kind === "videoFile" || kind === "quickTimeFile" ? "video" : "audio",
17281
- relationshipId: String(attribute2(node, "link") ?? attribute2(node, "embed") ?? "").trim() || void 0,
17282
- isLinked: attribute2(node, "link") !== void 0,
17617
+ relationshipId: linkId ?? embedId,
17618
+ // Embedded media legitimately uses r:link pointing at an INTERNAL
17619
+ // media part, so link presence alone does not imply a linked clip.
17620
+ // It is only truly linked when the referenced relationship is
17621
+ // external (TargetMode="External"), mirroring the OLE parser.
17622
+ isLinked: linkId !== void 0 && externalRelIds?.has(linkId) === true,
17283
17623
  name: kind === "wavAudioFile" ? String(attribute2(node, "name") ?? "") || void 0 : void 0,
17284
17624
  contentType: kind === "audioFile" ? String(attribute2(node, "contentType") ?? "") || void 0 : void 0,
17285
17625
  audioCdStart: kind === "audioCd" ? parseAudioCdPosition(child11(node, "st")) : void 0,
@@ -17436,6 +17776,45 @@ function withThemePlaceholderColor(themeColorMap, placeholderColor, operation) {
17436
17776
  }
17437
17777
  }
17438
17778
 
17779
+ // src/core/utils/slide-title.ts
17780
+ var TITLE_PLACEHOLDER_TYPES = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
17781
+ function getElementPlaceholderType(element) {
17782
+ const explicit = element.placeholderType;
17783
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
17784
+ return explicit.trim().toLowerCase();
17785
+ }
17786
+ const ph = xmlPath(element.rawXml, "p:nvSpPr", "p:nvPr", "p:ph");
17787
+ const type = xmlAttr(ph, "type");
17788
+ return type ? type.trim().toLowerCase() : void 0;
17789
+ }
17790
+ function getElementPlainText(element) {
17791
+ const maybe = element;
17792
+ if (typeof maybe.text === "string" && maybe.text.trim().length > 0) {
17793
+ return maybe.text.trim();
17794
+ }
17795
+ if (Array.isArray(maybe.textSegments)) {
17796
+ const joined = maybe.textSegments.map((segment) => typeof segment?.text === "string" ? segment.text : "").join("");
17797
+ return joined.trim();
17798
+ }
17799
+ return "";
17800
+ }
17801
+ function deriveSlideTitle(slide) {
17802
+ const elements = slide.elements ?? [];
17803
+ for (const element of elements) {
17804
+ const phType = getElementPlaceholderType(element);
17805
+ if (phType && TITLE_PLACEHOLDER_TYPES.has(phType)) {
17806
+ const text2 = getElementPlainText(element);
17807
+ if (text2) {
17808
+ return text2;
17809
+ }
17810
+ }
17811
+ }
17812
+ return "";
17813
+ }
17814
+ function deriveSlideTitles(slides) {
17815
+ return slides.map((slide) => deriveSlideTitle(slide));
17816
+ }
17817
+
17439
17818
  // src/converter/svg-chart-extended.ts
17440
17819
  var DEFAULT_COLORS = ["#4472C4", "#ED7D31", "#A5A5A5", "#FFC000", "#5B9BD5", "#70AD47"];
17441
17820
  function esc(value) {
@@ -20011,6 +20390,7 @@ var TextShapeXmlFactory = class {
20011
20390
  createXmlElement(init) {
20012
20391
  const { element } = init;
20013
20392
  const isText = element.type === "text";
20393
+ const isTextBox = element.locks?.txBox ?? isText;
20014
20394
  const name = isText ? "TextBox" : "Rectangle";
20015
20395
  const geometry = this.context.normalizePresetGeometry(element.shapeType);
20016
20396
  const adjustmentEntries = Object.entries(element.shapeAdjustments || {}).filter(
@@ -20030,7 +20410,7 @@ var TextShapeXmlFactory = class {
20030
20410
  "@_name": `${name} ${elementId}`
20031
20411
  },
20032
20412
  "p:cNvSpPr": {
20033
- "@_txBox": isText ? "1" : "0"
20413
+ "@_txBox": isTextBox ? "1" : "0"
20034
20414
  },
20035
20415
  "p:nvPr": {}
20036
20416
  },
@@ -20488,8 +20868,18 @@ var PptxPresentationSaveBuilder = class {
20488
20868
  init.rawSlideHeightEmu,
20489
20869
  init.rawSlideSizeType
20490
20870
  );
20491
- applyCustomShows(presentation, init.options?.customShows, init.xmlLookupService);
20492
- applySections(presentation, init.options?.sections, init.xmlLookupService);
20871
+ applyCustomShows(
20872
+ presentation,
20873
+ init.options?.customShows,
20874
+ init.xmlLookupService,
20875
+ init.slideReferenceRemap
20876
+ );
20877
+ applySections(
20878
+ presentation,
20879
+ init.options?.sections,
20880
+ init.xmlLookupService,
20881
+ init.slideReferenceRemap
20882
+ );
20493
20883
  this.applyPhotoAlbum(presentation, init.options?.photoAlbum);
20494
20884
  presentation = this.applyKinsoku(presentation, init.options?.kinsoku);
20495
20885
  this.applyModifyVerifier(presentation, init.options?.modifyVerifier);
@@ -20584,6 +20974,53 @@ var PptxPresentationSaveBuilder = class {
20584
20974
  }
20585
20975
  };
20586
20976
 
20977
+ // src/core/core/builders/slide-reference-remap.ts
20978
+ function buildSlideReferenceRemap(init) {
20979
+ const pathToNewRId = /* @__PURE__ */ new Map();
20980
+ for (const slide of init.slides) {
20981
+ pathToNewRId.set(slide.id, slide.rId);
20982
+ }
20983
+ const newRIdToNumeric = /* @__PURE__ */ new Map();
20984
+ for (const entry of init.rebuiltSlideIds) {
20985
+ const relationshipId2 = String(entry?.["@_r:id"] ?? "");
20986
+ const numericSlideId = String(entry?.["@_id"] ?? "");
20987
+ if (relationshipId2.length > 0 && numericSlideId.length > 0) {
20988
+ newRIdToNumeric.set(relationshipId2, numericSlideId);
20989
+ }
20990
+ }
20991
+ const rIdByOldRId = /* @__PURE__ */ new Map();
20992
+ const removedRIds = /* @__PURE__ */ new Set();
20993
+ let changed = false;
20994
+ for (const [oldRId, path2] of init.originalRIdToPath.entries()) {
20995
+ const newRId = pathToNewRId.get(path2);
20996
+ if (newRId === void 0) {
20997
+ removedRIds.add(oldRId);
20998
+ changed = true;
20999
+ continue;
21000
+ }
21001
+ rIdByOldRId.set(oldRId, newRId);
21002
+ if (newRId !== oldRId) {
21003
+ changed = true;
21004
+ }
21005
+ }
21006
+ const sldIdByOldSldId = /* @__PURE__ */ new Map();
21007
+ const removedSldIds = /* @__PURE__ */ new Set();
21008
+ for (const [oldSldId, path2] of init.originalSldIdToPath.entries()) {
21009
+ const newRId = pathToNewRId.get(path2);
21010
+ const newSldId = newRId === void 0 ? void 0 : newRIdToNumeric.get(newRId);
21011
+ if (newSldId === void 0) {
21012
+ removedSldIds.add(oldSldId);
21013
+ changed = true;
21014
+ continue;
21015
+ }
21016
+ sldIdByOldSldId.set(oldSldId, newSldId);
21017
+ if (newSldId !== oldSldId) {
21018
+ changed = true;
21019
+ }
21020
+ }
21021
+ return { rIdByOldRId, sldIdByOldSldId, removedRIds, removedSldIds, changed };
21022
+ }
21023
+
20587
21024
  // src/core/core/builders/PptxPresentationSlidesReconciler.ts
20588
21025
  var PptxPresentationSlidesReconciler = class {
20589
21026
  async reconcile(input) {
@@ -20629,6 +21066,10 @@ var PptxPresentationSlidesReconciler = class {
20629
21066
  const existingSlideIds = slideIdList ? this.ensureArray(slideIdList["p:sldId"]) : [];
20630
21067
  const slideIdByRid = /* @__PURE__ */ new Map();
20631
21068
  let maxNumericSlideId = 255;
21069
+ const originalRIdToPath = /* @__PURE__ */ new Map();
21070
+ for (const [relationshipId2, target] of slideTargetByRid.entries()) {
21071
+ originalRIdToPath.set(relationshipId2, input.toSlidePathFromTarget(target));
21072
+ }
20632
21073
  for (const slideIdEntry of existingSlideIds) {
20633
21074
  const relationshipId2 = slideIdEntry?.["@_r:id"];
20634
21075
  if (typeof relationshipId2 === "string" && relationshipId2.length > 0) {
@@ -20639,6 +21080,15 @@ var PptxPresentationSlidesReconciler = class {
20639
21080
  maxNumericSlideId = Math.max(maxNumericSlideId, numericSlideId);
20640
21081
  }
20641
21082
  }
21083
+ const originalSldIdToPath = /* @__PURE__ */ new Map();
21084
+ for (const slideIdEntry of existingSlideIds) {
21085
+ const relationshipId2 = String(slideIdEntry?.["@_r:id"] ?? "");
21086
+ const numericSlideId = String(slideIdEntry?.["@_id"] ?? "");
21087
+ const slidePath = originalRIdToPath.get(relationshipId2);
21088
+ if (numericSlideId.length > 0 && slidePath !== void 0) {
21089
+ originalSldIdToPath.set(numericSlideId, slidePath);
21090
+ }
21091
+ }
20642
21092
  for (let index = 0; index < input.slides.length; index++) {
20643
21093
  const slide = input.slides[index];
20644
21094
  slide.slideNumber = index + 1;
@@ -20675,6 +21125,7 @@ var PptxPresentationSlidesReconciler = class {
20675
21125
  ];
20676
21126
  presentationRelsData["Relationships"] = relRoot;
20677
21127
  input.zip.file("ppt/_rels/presentation.xml.rels", input.xmlBuilder.build(presentationRelsData));
21128
+ const rebuiltSlideIds = [];
20678
21129
  if (presentation && slideIdList && input.presentationData) {
20679
21130
  slideIdList["p:sldId"] = input.slides.map((slide) => {
20680
21131
  const existing = slideIdByRid.get(slide.rId);
@@ -20687,11 +21138,18 @@ var PptxPresentationSlidesReconciler = class {
20687
21138
  "@_r:id": slide.rId
20688
21139
  };
20689
21140
  });
21141
+ rebuiltSlideIds.push(...slideIdList["p:sldId"]);
20690
21142
  input.presentationData["p:presentation"] = this.insertSlideIdListInOrder(
20691
21143
  presentation,
20692
21144
  slideIdList
20693
21145
  );
20694
21146
  }
21147
+ return buildSlideReferenceRemap({
21148
+ slides: input.slides,
21149
+ originalRIdToPath,
21150
+ originalSldIdToPath,
21151
+ rebuiltSlideIds
21152
+ });
20695
21153
  }
20696
21154
  /**
20697
21155
  * Return a new presentation XML object whose `p:sldIdLst` child sits in the
@@ -21277,7 +21735,7 @@ var PptxSlideNotesPartUpdater = class {
21277
21735
 
21278
21736
  // src/core/core/builders/PptxSlideBackgroundBuilder.ts
21279
21737
  var PptxSlideBackgroundBuilder = class {
21280
- applyBackground(init) {
21738
+ async applyBackground(init) {
21281
21739
  const hasBackgroundColor = typeof init.slide.backgroundColor === "string" && init.slide.backgroundColor.length > 0 && init.slide.backgroundColor !== "transparent";
21282
21740
  const rawBackgroundImage = typeof init.slide.backgroundImage === "string" ? init.slide.backgroundImage : "";
21283
21741
  const hasBackgroundImage = rawBackgroundImage.length > 0;
@@ -21298,8 +21756,8 @@ var PptxSlideBackgroundBuilder = class {
21298
21756
  return;
21299
21757
  }
21300
21758
  const backgroundProperties = {};
21301
- if (hasDataUrlBackgroundImage) {
21302
- const parsedBackgroundImage = init.parseDataUrlToBytes(rawBackgroundImage);
21759
+ if (hasBackgroundImage) {
21760
+ const parsedBackgroundImage = await init.resolveImageToBytes(rawBackgroundImage);
21303
21761
  if (parsedBackgroundImage) {
21304
21762
  const backgroundImagePath = init.saveState.nextMediaPath(parsedBackgroundImage.extension);
21305
21763
  init.zip.file(backgroundImagePath, parsedBackgroundImage.bytes);
@@ -21317,8 +21775,11 @@ var PptxSlideBackgroundBuilder = class {
21317
21775
  },
21318
21776
  BLIP_FILL_ORDER
21319
21777
  );
21778
+ } else {
21779
+ init.reportUnsupportedBackground?.(rawBackgroundImage);
21320
21780
  }
21321
- } else if (hasBackgroundColor && init.slide.backgroundColor) {
21781
+ }
21782
+ if (backgroundProperties["a:blipFill"] === void 0 && hasBackgroundColor && init.slide.backgroundColor) {
21322
21783
  backgroundProperties["a:solidFill"] = {
21323
21784
  "a:srgbClr": {
21324
21785
  "@_val": init.slide.backgroundColor.replace("#", "").toUpperCase()
@@ -21335,6 +21796,11 @@ var PptxSlideBackgroundBuilder = class {
21335
21796
  backgroundProperties["@_shadeToTitle"] = "0";
21336
21797
  }
21337
21798
  if (!hasFillChild) {
21799
+ if (existingBg !== void 0) {
21800
+ this.reorderCSldBgFirst(cSld, existingBg);
21801
+ init.slideNode["p:cSld"] = cSld;
21802
+ return;
21803
+ }
21338
21804
  delete cSld["p:bg"];
21339
21805
  init.slideNode["p:cSld"] = cSld;
21340
21806
  return;
@@ -21544,11 +22010,15 @@ var PptxColorTransformCodec = class {
21544
22010
  }
21545
22011
  if (colorChoice["a:scrgbClr"]) {
21546
22012
  const scrgb = colorChoice["a:scrgbClr"];
21547
- const red = this.percentAttrToUnit(scrgb["@_r"]);
21548
- const green = this.percentAttrToUnit(scrgb["@_g"]);
21549
- const blue = this.percentAttrToUnit(scrgb["@_b"]);
22013
+ const red = parseDrawingFraction(scrgb["@_r"]);
22014
+ const green = parseDrawingFraction(scrgb["@_g"]);
22015
+ const blue = parseDrawingFraction(scrgb["@_b"]);
21550
22016
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
21551
- const base = this.rgbToHex(red * 255, green * 255, blue * 255);
22017
+ const base = this.rgbToHex(
22018
+ scrgbLinearToSrgb8(red),
22019
+ scrgbLinearToSrgb8(green),
22020
+ scrgbLinearToSrgb8(blue)
22021
+ );
21552
22022
  return this.applyColorTransforms(base, scrgb);
21553
22023
  }
21554
22024
  }
@@ -21639,8 +22109,8 @@ var PptxColorTransformCodec = class {
21639
22109
  };
21640
22110
  }
21641
22111
  rgbToHex(r, g, b) {
21642
- const toHex3 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
21643
- return `#${toHex3(r)}${toHex3(g)}${toHex3(b)}`;
22112
+ const toHex4 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
22113
+ return `#${toHex4(r)}${toHex4(g)}${toHex4(b)}`;
21644
22114
  }
21645
22115
  applyColorTransforms(baseColor, colorNode) {
21646
22116
  return applyDrawingColorTransforms(baseColor, colorNode);
@@ -21728,6 +22198,22 @@ function mergeDrawingFillXml(original, generated, modeledChildren, childOrder2)
21728
22198
  }
21729
22199
 
21730
22200
  // src/core/core/builders/PptxGradientStyleCodec.ts
22201
+ function extractGradientTileRect(gradFill) {
22202
+ const tileRect = drawingChild(gradFill, "tileRect");
22203
+ if (!tileRect) {
22204
+ return void 0;
22205
+ }
22206
+ const toFraction = (raw) => {
22207
+ const parsed = Number.parseInt(String(raw ?? "0"), 10);
22208
+ return Number.isFinite(parsed) ? parsed / 1e5 : 0;
22209
+ };
22210
+ return {
22211
+ l: toFraction(tileRect["@_l"]),
22212
+ t: toFraction(tileRect["@_t"]),
22213
+ r: toFraction(tileRect["@_r"]),
22214
+ b: toFraction(tileRect["@_b"])
22215
+ };
22216
+ }
21731
22217
  var PptxGradientStyleCodec = class {
21732
22218
  context;
21733
22219
  constructor(context) {
@@ -21838,6 +22324,9 @@ var PptxGradientStyleCodec = class {
21838
22324
  b: Number.isFinite(b) ? this.context.clampUnitInterval(b / 1e5) : 0
21839
22325
  };
21840
22326
  }
22327
+ extractGradientTileRect(gradFill) {
22328
+ return extractGradientTileRect(gradFill);
22329
+ }
21841
22330
  extractGradientFlip(gradFill) {
21842
22331
  const flipRaw = String(gradFill["@_flip"] || "").trim().toLowerCase();
21843
22332
  if (flipRaw === "x" || flipRaw === "y" || flipRaw === "xy" || flipRaw === "none") {
@@ -22009,6 +22498,15 @@ var PptxGradientStyleCodec = class {
22009
22498
  }
22010
22499
  gradientXml["a:lin"] = linNode;
22011
22500
  }
22501
+ if (shapeStyle.fillGradientTileRect) {
22502
+ const tr = shapeStyle.fillGradientTileRect;
22503
+ gradientXml["a:tileRect"] = {
22504
+ "@_l": String(Math.round(tr.l * 1e5)),
22505
+ "@_t": String(Math.round(tr.t * 1e5)),
22506
+ "@_r": String(Math.round(tr.r * 1e5)),
22507
+ "@_b": String(Math.round(tr.b * 1e5))
22508
+ };
22509
+ }
22012
22510
  return mergeDrawingFillXml(
22013
22511
  shapeStyle.fillGradientXml,
22014
22512
  gradientXml,
@@ -23487,7 +23985,7 @@ var PptxColorStyleCodec = class {
23487
23985
  const alphaMod = this.percentAttrToUnit(
23488
23986
  choiceNode["a:alphaMod"]?.["@_val"]
23489
23987
  );
23490
- const alphaOff = this.percentAttrToUnit(
23988
+ const alphaOff = this.signedPercentToUnit(
23491
23989
  choiceNode["a:alphaOff"]?.["@_val"]
23492
23990
  );
23493
23991
  if (alpha === void 0 && alphaMod === void 0 && alphaOff === void 0) {
@@ -23502,6 +24000,18 @@ var PptxColorStyleCodec = class {
23502
24000
  }
23503
24001
  return this.clampUnitInterval(opacity2);
23504
24002
  }
24003
+ /**
24004
+ * Parse an OOXML percentage (thousandths, `100000` = 100%) into a fraction
24005
+ * WITHOUT clamping to [0, 1]. Used for additive offsets like `a:alphaOff`
24006
+ * that legitimately carry negative values.
24007
+ */
24008
+ signedPercentToUnit(value) {
24009
+ const parsed = Number.parseFloat(String(value ?? "").trim());
24010
+ if (!Number.isFinite(parsed)) {
24011
+ return void 0;
24012
+ }
24013
+ return parsed / 1e5;
24014
+ }
23505
24015
  colorWithOpacity(color2, opacity2) {
23506
24016
  if (opacity2 === void 0) {
23507
24017
  return color2;
@@ -23610,26 +24120,49 @@ function applyScene3dStyle(shapeProps, style) {
23610
24120
  const camera = scene3dNode["a:camera"];
23611
24121
  const lightRig = scene3dNode["a:lightRig"];
23612
24122
  const cameraRot = camera?.["a:rot"];
24123
+ const lightRigRot = lightRig?.["a:rot"];
23613
24124
  style.scene3d = {
23614
24125
  cameraPreset: String(camera?.["@_prst"] || "").trim() || void 0,
23615
- cameraRotX: cameraRot?.["@_lat"] !== void 0 ? parseInt(String(cameraRot["@_lat"]), 10) : void 0,
23616
- cameraRotY: cameraRot?.["@_lon"] !== void 0 ? parseInt(String(cameraRot["@_lon"]), 10) : void 0,
23617
- cameraRotZ: cameraRot?.["@_rev"] !== void 0 ? parseInt(String(cameraRot["@_rev"]), 10) : void 0,
24126
+ cameraFieldOfView: intAttr(camera?.["@_fov"]),
24127
+ cameraZoom: floatAttr(camera?.["@_zoom"]),
24128
+ cameraRotX: intAttr(cameraRot?.["@_lat"]),
24129
+ cameraRotY: intAttr(cameraRot?.["@_lon"]),
24130
+ cameraRotZ: intAttr(cameraRot?.["@_rev"]),
23618
24131
  lightRigType: String(lightRig?.["@_rig"] || "").trim() || void 0,
23619
- lightRigDirection: String(lightRig?.["@_dir"] || "").trim() || void 0
24132
+ lightRigDirection: String(lightRig?.["@_dir"] || "").trim() || void 0,
24133
+ lightRigRotX: intAttr(lightRigRot?.["@_lat"]),
24134
+ lightRigRotY: intAttr(lightRigRot?.["@_lon"]),
24135
+ lightRigRotZ: intAttr(lightRigRot?.["@_rev"])
23620
24136
  };
23621
24137
  const backdrop = scene3dNode["a:backdrop"];
23622
24138
  if (backdrop) {
23623
24139
  style.scene3d.hasBackdrop = true;
23624
24140
  const anchor = backdrop["a:anchor"];
23625
- const anchorAttrs = anchor;
23626
- if (anchorAttrs) {
23627
- style.scene3d.backdropAnchorX = parseInt(String(anchorAttrs["@_x"] || "0"), 10);
23628
- style.scene3d.backdropAnchorY = parseInt(String(anchorAttrs["@_y"] || "0"), 10);
23629
- style.scene3d.backdropAnchorZ = parseInt(String(anchorAttrs["@_z"] || "0"), 10);
24141
+ if (anchor) {
24142
+ style.scene3d.backdropAnchorX = intAttr(anchor["@_x"]) ?? 0;
24143
+ style.scene3d.backdropAnchorY = intAttr(anchor["@_y"]) ?? 0;
24144
+ style.scene3d.backdropAnchorZ = intAttr(anchor["@_z"]) ?? 0;
24145
+ }
24146
+ const norm = backdrop["a:norm"];
24147
+ if (norm) {
24148
+ style.scene3d.backdropNormalX = intAttr(norm["@_dx"]) ?? 0;
24149
+ style.scene3d.backdropNormalY = intAttr(norm["@_dy"]) ?? 0;
24150
+ style.scene3d.backdropNormalZ = intAttr(norm["@_dz"]) ?? 0;
24151
+ }
24152
+ const up = backdrop["a:up"];
24153
+ if (up) {
24154
+ style.scene3d.backdropUpX = intAttr(up["@_dx"]) ?? 0;
24155
+ style.scene3d.backdropUpY = intAttr(up["@_dy"]) ?? 0;
24156
+ style.scene3d.backdropUpZ = intAttr(up["@_dz"]) ?? 0;
23630
24157
  }
23631
24158
  }
23632
24159
  }
24160
+ function intAttr(value) {
24161
+ return value !== void 0 ? parseInt(String(value), 10) : void 0;
24162
+ }
24163
+ function floatAttr(value) {
24164
+ return value !== void 0 ? parseFloat(String(value)) : void 0;
24165
+ }
23633
24166
  function applyShape3dStyle(shapeProps, style, context) {
23634
24167
  const shape3dNode = shapeProps["a:sp3d"];
23635
24168
  if (!shape3dNode) {
@@ -23662,10 +24195,12 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23662
24195
  }
23663
24196
  const hiddenLineFill = hiddenLineProps["a:solidFill"];
23664
24197
  if (hiddenLineFill) {
24198
+ style.strokeFillMode = "solid";
23665
24199
  style.strokeColor = context.parseColor(hiddenLineFill);
23666
24200
  style.strokeOpacity = context.extractColorOpacity(hiddenLineFill);
23667
24201
  }
23668
24202
  } else {
24203
+ style.strokeFillMode = "none";
23669
24204
  style.strokeWidth = 0;
23670
24205
  style.strokeColor = "transparent";
23671
24206
  }
@@ -23683,6 +24218,7 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23683
24218
  }
23684
24219
  function applyStrokeColor(lineNode, style, context) {
23685
24220
  if (lineNode["a:solidFill"]) {
24221
+ style.strokeFillMode = "solid";
23686
24222
  const lineFill = lineNode["a:solidFill"];
23687
24223
  style.strokeColor = context.parseColor(lineFill);
23688
24224
  style.strokeOpacity = context.extractColorOpacity(lineFill);
@@ -23691,10 +24227,15 @@ function applyStrokeColor(lineNode, style, context) {
23691
24227
  style.strokeColorXml = strokeColorXml;
23692
24228
  }
23693
24229
  } else if (lineNode["a:gradFill"]) {
23694
- style.strokeColor = context.extractGradientFillColor(lineNode["a:gradFill"]);
23695
- style.strokeOpacity = context.extractGradientOpacity(lineNode["a:gradFill"]);
24230
+ style.strokeFillMode = "gradient";
24231
+ const lineGradFill = lineNode["a:gradFill"];
24232
+ style.strokeGradientXml = lineGradFill;
24233
+ style.strokeColor = context.extractGradientFillColor(lineGradFill);
24234
+ style.strokeOpacity = context.extractGradientOpacity(lineGradFill);
23696
24235
  } else if (lineNode["a:pattFill"]) {
24236
+ style.strokeFillMode = "pattern";
23697
24237
  const linePatternFill = lineNode["a:pattFill"];
24238
+ style.strokePatternXml = linePatternFill;
23698
24239
  style.strokeColor = context.parseColor(linePatternFill["a:fgClr"]) || context.parseColor(linePatternFill["a:bgClr"]);
23699
24240
  style.strokeOpacity = context.extractColorOpacity(linePatternFill["a:fgClr"]) || context.extractColorOpacity(linePatternFill["a:bgClr"]);
23700
24241
  }
@@ -23823,6 +24364,10 @@ var PptxShapeStyleExtractor = class {
23823
24364
  style.fillGradientPathType = this.context.extractGradientPathType(gradFill);
23824
24365
  style.fillGradientFocalPoint = this.context.extractGradientFocalPoint(gradFill);
23825
24366
  style.fillGradientFillToRect = this.context.extractGradientFillToRect(gradFill);
24367
+ const gradTileRect = extractGradientTileRect(gradFill);
24368
+ if (gradTileRect) {
24369
+ style.fillGradientTileRect = gradTileRect;
24370
+ }
23826
24371
  const gradFlip = this.context.extractGradientFlip(gradFill);
23827
24372
  if (gradFlip) {
23828
24373
  style.fillGradientFlip = gradFlip;
@@ -24512,7 +25057,10 @@ var PptxMediaDataParser = class {
24512
25057
  parseMediaData(graphicData, slidePath) {
24513
25058
  const result = {};
24514
25059
  try {
24515
- const reference = parseDrawingMediaReference(graphicData);
25060
+ const reference = parseDrawingMediaReference(
25061
+ graphicData,
25062
+ this.context.externalRelsMap.get(slidePath)
25063
+ );
24516
25064
  if (reference) {
24517
25065
  result.mediaType = reference.mediaType;
24518
25066
  result.mediaReferenceKind = reference.kind;
@@ -25013,6 +25561,7 @@ var PptxLoadDataBuilder = class {
25013
25561
  layoutOptions = [];
25014
25562
  headerFooter;
25015
25563
  presentationProperties;
25564
+ viewProperties;
25016
25565
  customShows;
25017
25566
  sections;
25018
25567
  warnings = [];
@@ -25072,6 +25621,10 @@ var PptxLoadDataBuilder = class {
25072
25621
  this.presentationProperties = presentationProperties;
25073
25622
  return this;
25074
25623
  }
25624
+ withViewProperties(viewProperties) {
25625
+ this.viewProperties = viewProperties;
25626
+ return this;
25627
+ }
25075
25628
  withCustomShows(customShows) {
25076
25629
  this.customShows = customShows;
25077
25630
  return this;
@@ -25209,6 +25762,7 @@ var PptxLoadDataBuilder = class {
25209
25762
  layoutOptions: this.layoutOptions,
25210
25763
  headerFooter: this.headerFooter,
25211
25764
  presentationProperties: this.presentationProperties,
25765
+ viewProperties: this.viewProperties,
25212
25766
  customShows: this.customShows,
25213
25767
  sections: this.sections,
25214
25768
  warnings: this.warnings,
@@ -25591,7 +26145,7 @@ var PptxSlideCommentsXmlFactory = class {
25591
26145
  const createdAtIso = this.resolveCreatedAt(comment.createdAt);
25592
26146
  const x = init.saveState.toEmu(comment.x, 0);
25593
26147
  const y = init.saveState.toEmu(comment.y, 0);
25594
- return {
26148
+ const node = {
25595
26149
  ...withoutChildrenByLocalName(comment.rawXml ?? {}, /* @__PURE__ */ new Set(["pos", "text"])),
25596
26150
  "@_authorId": authorId,
25597
26151
  "@_dt": createdAtIso,
@@ -25602,6 +26156,28 @@ var PptxSlideCommentsXmlFactory = class {
25602
26156
  },
25603
26157
  "p:text": String(comment.text || "")
25604
26158
  };
26159
+ this.applyResolvedState(node, comment);
26160
+ return node;
26161
+ }
26162
+ /**
26163
+ * Reflect the (possibly edited) `resolved` flag onto the legacy comment
26164
+ * node. PowerPoint's legacy comment schema has no standard resolved marker,
26165
+ * but the parser reads a non-standard `@_done` / `@_resolved` attribute, so
26166
+ * we re-emit the current state rather than leaving the stale value carried
26167
+ * over from `rawXml`. The original attribute name is preserved when present.
26168
+ */
26169
+ applyResolvedState(node, comment) {
26170
+ const raw = comment.rawXml;
26171
+ const hadResolvedAttr = raw?.["@_resolved"] !== void 0;
26172
+ const hadDoneAttr = raw?.["@_done"] !== void 0;
26173
+ const key = hadResolvedAttr && !hadDoneAttr ? "@_resolved" : "@_done";
26174
+ delete node["@_done"];
26175
+ delete node["@_resolved"];
26176
+ if (comment.resolved === true) {
26177
+ node[key] = "1";
26178
+ } else if (hadResolvedAttr || hadDoneAttr) {
26179
+ node[key] = "0";
26180
+ }
25605
26181
  }
25606
26182
  resolveCreatedAt(createdAt) {
25607
26183
  const candidate = String(createdAt || "").trim();
@@ -25963,6 +26539,94 @@ var PptxCompatibilityService = class {
25963
26539
  }
25964
26540
  };
25965
26541
 
26542
+ // src/core/utils/app-properties-titles.ts
26543
+ var SLIDE_TITLES_NAME = "Slide Titles";
26544
+ function coerceText(value) {
26545
+ if (typeof value === "string") {
26546
+ return value;
26547
+ }
26548
+ if (typeof value === "number" || typeof value === "boolean") {
26549
+ return String(value);
26550
+ }
26551
+ if (isXmlNode(value)) {
26552
+ const text2 = value["#text"];
26553
+ return text2 === void 0 || text2 === null ? "" : String(text2);
26554
+ }
26555
+ return "";
26556
+ }
26557
+ function coerceCount(value) {
26558
+ const parsed = Number.parseInt(coerceText(value), 10);
26559
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
26560
+ }
26561
+ function readLpstrList(vector) {
26562
+ if (!vector) {
26563
+ return [];
26564
+ }
26565
+ const raw = vector["vt:lpstr"];
26566
+ if (raw === void 0 || raw === null) {
26567
+ return [];
26568
+ }
26569
+ return (Array.isArray(raw) ? raw : [raw]).map(coerceText);
26570
+ }
26571
+ function isSlideTitlesCategory(name) {
26572
+ const normalized = name.trim().toLowerCase();
26573
+ return normalized === "slide titles" || normalized.includes("slide") && normalized.includes("title");
26574
+ }
26575
+ function readCategories(headingPairs, titlesOfParts) {
26576
+ const variants = xmlChildren(xmlChild(headingPairs, "vt:vector"), "vt:variant");
26577
+ const entries = readLpstrList(xmlChild(titlesOfParts, "vt:vector"));
26578
+ const categories = [];
26579
+ let offset = 0;
26580
+ for (let i = 0; i + 1 < variants.length; i += 2) {
26581
+ const name = coerceText(variants[i]["vt:lpstr"]);
26582
+ const count = coerceCount(variants[i + 1]["vt:i4"]);
26583
+ categories.push({ name, entries: entries.slice(offset, offset + count) });
26584
+ offset += count;
26585
+ }
26586
+ return categories;
26587
+ }
26588
+ function writeHeadingPairs(appProps, categories) {
26589
+ const variants = [];
26590
+ for (const category of categories) {
26591
+ variants.push({ "vt:lpstr": category.name });
26592
+ variants.push({ "vt:i4": String(category.entries.length) });
26593
+ }
26594
+ appProps["HeadingPairs"] = {
26595
+ "vt:vector": {
26596
+ "@_size": String(variants.length),
26597
+ "@_baseType": "variant",
26598
+ "vt:variant": variants
26599
+ }
26600
+ };
26601
+ }
26602
+ function writeTitlesOfParts(appProps, categories) {
26603
+ const allEntries = categories.flatMap((category) => category.entries);
26604
+ const lpstr = allEntries.map((entry) => ({ "#text": entry }));
26605
+ appProps["TitlesOfParts"] = {
26606
+ "vt:vector": {
26607
+ "@_size": String(allEntries.length),
26608
+ "@_baseType": "lpstr",
26609
+ "vt:lpstr": lpstr
26610
+ }
26611
+ };
26612
+ }
26613
+ function applySlideTitlesToAppProps(appProps, titles) {
26614
+ const headingPairs = xmlChild(appProps, "HeadingPairs");
26615
+ if (!headingPairs) {
26616
+ return;
26617
+ }
26618
+ const titlesOfParts = xmlChild(appProps, "TitlesOfParts");
26619
+ const categories = readCategories(headingPairs, titlesOfParts);
26620
+ const slideCategory = categories.find((category) => isSlideTitlesCategory(category.name));
26621
+ if (slideCategory) {
26622
+ slideCategory.entries = titles;
26623
+ } else {
26624
+ categories.push({ name: SLIDE_TITLES_NAME, entries: titles });
26625
+ }
26626
+ writeHeadingPairs(appProps, categories);
26627
+ writeTitlesOfParts(appProps, categories);
26628
+ }
26629
+
25966
26630
  // src/core/services/PptxDocumentPropertiesUpdater.ts
25967
26631
  var PptxDocumentPropertiesUpdater = class {
25968
26632
  context;
@@ -26026,6 +26690,7 @@ var PptxDocumentPropertiesUpdater = class {
26026
26690
  appProps["Slides"] = String(slides.length);
26027
26691
  appProps["HiddenSlides"] = String(hiddenSlidesCount);
26028
26692
  appProps["Notes"] = String(notesCount);
26693
+ this.updateSlideTitleProperties(appProps, slides);
26029
26694
  appData["Properties"] = appProps;
26030
26695
  this.context.zip.file("docProps/app.xml", this.context.builder.build(appData));
26031
26696
  } catch (error) {
@@ -26068,6 +26733,15 @@ var PptxDocumentPropertiesUpdater = class {
26068
26733
  }
26069
26734
  }
26070
26735
  }
26736
+ /**
26737
+ * Recompute `TitlesOfParts` / `HeadingPairs` from the current slide set so
26738
+ * the per-slide title list in `app.xml` stays consistent after slides are
26739
+ * added, removed, or retitled. Delegates the vector rebuild to a pure
26740
+ * helper; here we only derive the ordered titles.
26741
+ */
26742
+ updateSlideTitleProperties(appProps, slides) {
26743
+ applySlideTitlesToAppProps(appProps, deriveSlideTitles(slides));
26744
+ }
26071
26745
  applyAppPropertiesOverrides(appProps, overrides) {
26072
26746
  if (!overrides) {
26073
26747
  return;
@@ -27687,6 +28361,16 @@ function extractChildKeyframes(childTnList) {
27687
28361
  }
27688
28362
  return void 0;
27689
28363
  }
28364
+ function parseTimingPercentFraction(raw) {
28365
+ if (raw === void 0 || raw === null) {
28366
+ return void 0;
28367
+ }
28368
+ const parsed = Number.parseInt(String(raw), 10);
28369
+ if (!Number.isFinite(parsed) || parsed <= 0) {
28370
+ return void 0;
28371
+ }
28372
+ return Math.min(1, parsed / 1e5);
28373
+ }
27690
28374
  function extractRepeatInfo(cTn) {
27691
28375
  let repeatCount;
27692
28376
  let autoReverse;
@@ -28165,8 +28849,11 @@ var PptxNativeAnimationService = class {
28165
28849
  const nodeType = String(cTn["@_nodeType"] || "");
28166
28850
  const presetClass = cTn["@_presetClass"];
28167
28851
  const presetId = cTn["@_presetID"] ? Number.parseInt(String(cTn["@_presetID"]), 10) : void 0;
28852
+ const presetSubtype = cTn["@_presetSubtype"] !== void 0 ? Number.parseInt(String(cTn["@_presetSubtype"]), 10) : void 0;
28168
28853
  const durationMs = cTn["@_dur"] ? Number.parseInt(String(cTn["@_dur"]), 10) : void 0;
28169
28854
  const delayMs = cTn["@_delay"] ? Number.parseInt(String(cTn["@_delay"]), 10) : void 0;
28855
+ const accel = parseTimingPercentFraction(cTn["@_accel"]);
28856
+ const decel = parseTimingPercentFraction(cTn["@_decel"]);
28170
28857
  let trigger = currentTrigger;
28171
28858
  if (nodeType === "afterPrevious" || nodeType === "afterPrev") {
28172
28859
  trigger = "afterPrevious";
@@ -28216,8 +28903,11 @@ var PptxNativeAnimationService = class {
28216
28903
  trigger,
28217
28904
  presetClass: validPresetClass,
28218
28905
  presetId,
28906
+ presetSubtype,
28219
28907
  durationMs,
28220
28908
  delayMs,
28909
+ accel,
28910
+ decel,
28221
28911
  triggerDelayMs: trigger === "afterDelay" ? delayMs : void 0,
28222
28912
  motionPath: childMotion.motionPath,
28223
28913
  motionOrigin: childMotion.motionOrigin,
@@ -28526,6 +29216,74 @@ function buildP14ExtLst(transitionType, direction, orient, pattern, rawExtLst, x
28526
29216
  return { "p:ext": transitionExt };
28527
29217
  }
28528
29218
 
29219
+ // src/core/services/p15-transition-parser.ts
29220
+ var P15_TRANSITION_PRESETS = /* @__PURE__ */ new Set([
29221
+ "fallOver",
29222
+ "drape",
29223
+ "curtains",
29224
+ "wind",
29225
+ "prestige",
29226
+ "fracture",
29227
+ "crush",
29228
+ "peelOff",
29229
+ "pageCurlDouble",
29230
+ "pageCurlSingle",
29231
+ "airplane",
29232
+ "origami"
29233
+ ]);
29234
+ var PRSTTRANS_EXT_URI = "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}";
29235
+ function optionalBoolean(value) {
29236
+ const valueToken = value === void 0 || value === null ? "" : String(value).trim().toLowerCase();
29237
+ if (valueToken === "1" || valueToken === "true") {
29238
+ return true;
29239
+ }
29240
+ if (valueToken === "0" || valueToken === "false") {
29241
+ return false;
29242
+ }
29243
+ return void 0;
29244
+ }
29245
+ function parseP15FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
29246
+ const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
29247
+ for (const ext of extEntries) {
29248
+ if (!ext) {
29249
+ continue;
29250
+ }
29251
+ for (const [key, value] of Object.entries(ext)) {
29252
+ if (key.startsWith("@_")) {
29253
+ continue;
29254
+ }
29255
+ if (getXmlLocalName(key) !== "prstTrans") {
29256
+ continue;
29257
+ }
29258
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29259
+ continue;
29260
+ }
29261
+ const detail = value;
29262
+ const prst = String(detail["@_prst"] || "").trim();
29263
+ if (!P15_TRANSITION_PRESETS.has(prst)) {
29264
+ continue;
29265
+ }
29266
+ return {
29267
+ type: prst,
29268
+ invX: optionalBoolean(detail["@_invX"]),
29269
+ invY: optionalBoolean(detail["@_invY"])
29270
+ };
29271
+ }
29272
+ }
29273
+ return void 0;
29274
+ }
29275
+ function buildP15ExtLst(transitionType, invX, invY) {
29276
+ const prstTrans = {
29277
+ "@_xmlns:p15": "http://schemas.microsoft.com/office/powerpoint/2012/main",
29278
+ "@_prst": transitionType
29279
+ };
29280
+ const ext = {
29281
+ "@_uri": PRSTTRANS_EXT_URI,
29282
+ "p15:prstTrans": prstTrans
29283
+ };
29284
+ return { "p:ext": ext };
29285
+ }
29286
+
28529
29287
  // src/core/services/slide-transition-xml.ts
28530
29288
  var STANDARD_TRANSITION_TYPES = /* @__PURE__ */ new Set([
28531
29289
  "fade",
@@ -28591,7 +29349,7 @@ function parseTransitionDetails(node, localName21) {
28591
29349
  if (pattern) {
28592
29350
  result.pattern = pattern;
28593
29351
  }
28594
- const thruBlk = optionalBoolean(detail["@_thruBlk"]);
29352
+ const thruBlk = optionalBoolean2(detail["@_thruBlk"]);
28595
29353
  if (thruBlk !== void 0) {
28596
29354
  result.thruBlk = thruBlk;
28597
29355
  }
@@ -28602,7 +29360,7 @@ function parseTransitionAttributes(node) {
28602
29360
  const speedToken = token(node["@_spd"]);
28603
29361
  const speed = SPEEDS.has(speedToken) ? speedToken : void 0;
28604
29362
  const durationMs = unsignedInteger2(node["@_dur"] ?? node["@_p14:dur"], 1);
28605
- const advanceOnClick = optionalBoolean(node["@_advClick"]);
29363
+ const advanceOnClick = optionalBoolean2(node["@_advClick"]);
28606
29364
  const advanceAfterMs = unsignedInteger2(node["@_advTm"]);
28607
29365
  return { speed, durationMs, advanceOnClick, advanceAfterMs };
28608
29366
  }
@@ -28616,7 +29374,7 @@ function parseTransitionSound(raw, lookup, localName21) {
28616
29374
  return {
28617
29375
  soundRId: sound ? attributeByLocalName(sound, "embed", localName21) : void 0,
28618
29376
  soundName: sound ? attributeByLocalName(sound, "name", localName21) : void 0,
28619
- soundLoop: optionalBoolean(start["@_loop"])
29377
+ soundLoop: optionalBoolean2(start["@_loop"])
28620
29378
  };
28621
29379
  }
28622
29380
  const stopSound = Object.keys(raw).some(
@@ -28725,7 +29483,7 @@ function attributeByLocalName(node, name, localName21) {
28725
29483
  function token(value) {
28726
29484
  return value === void 0 || value === null ? "" : String(value).trim();
28727
29485
  }
28728
- function optionalBoolean(value) {
29486
+ function optionalBoolean2(value) {
28729
29487
  const valueToken = token(value).toLowerCase();
28730
29488
  if (!valueToken) {
28731
29489
  return void 0;
@@ -28771,6 +29529,7 @@ var PptxSlideTransitionService = class {
28771
29529
  const { spokes, thruBlk, rawSoundAction, rawExtLst } = details;
28772
29530
  if (rawExtLst && transitionType === "cut") {
28773
29531
  const p14Result = parseP14FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
29532
+ const p15Result = p14Result ? void 0 : parseP15FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
28774
29533
  if (p14Result) {
28775
29534
  transitionType = p14Result.type;
28776
29535
  if (p14Result.direction) {
@@ -28782,6 +29541,8 @@ var PptxSlideTransitionService = class {
28782
29541
  if (p14Result.pattern) {
28783
29542
  pattern = p14Result.pattern;
28784
29543
  }
29544
+ } else if (p15Result) {
29545
+ transitionType = p15Result.type;
28785
29546
  } else if (this.parseMorphFromExtLst(rawExtLst)) {
28786
29547
  transitionType = "morph";
28787
29548
  }
@@ -28863,6 +29624,7 @@ var PptxSlideTransitionService = class {
28863
29624
  }
28864
29625
  const transitionType = transition.type || "cut";
28865
29626
  const isP14Type = P14_TRANSITION_TYPES.has(transitionType);
29627
+ const isP15Type = P15_TRANSITION_PRESETS.has(transitionType);
28866
29628
  const isMorphType = transitionType === "morph";
28867
29629
  const node = createPreservedTransitionNode(transition.rawTransition, this.getXmlLocalName);
28868
29630
  if (isP14Type) {
@@ -28875,6 +29637,8 @@ var PptxSlideTransitionService = class {
28875
29637
  this.xmlLookupService,
28876
29638
  this.getXmlLocalName
28877
29639
  );
29640
+ } else if (isP15Type) {
29641
+ node["p:extLst"] = transition.rawExtLst ?? buildP15ExtLst(transitionType);
28878
29642
  } else if (isMorphType) {
28879
29643
  node["p:extLst"] = this.buildMorphExtLst(transition.rawExtLst);
28880
29644
  } else {
@@ -28885,7 +29649,7 @@ var PptxSlideTransitionService = class {
28885
29649
  if (soundAction) {
28886
29650
  node["p:sndAc"] = soundAction;
28887
29651
  }
28888
- if (transition.rawExtLst && !isP14Type && !isMorphType) {
29652
+ if (transition.rawExtLst && !isP14Type && !isP15Type && !isMorphType) {
28889
29653
  node["p:extLst"] = transition.rawExtLst;
28890
29654
  }
28891
29655
  return node;
@@ -31902,6 +32666,128 @@ function applySmartArtConnectionAttributes(xml, connection, fallbackModelId) {
31902
32666
  applyNullableAttribute(xml, "@_presId", connection.presentationId);
31903
32667
  }
31904
32668
 
32669
+ // src/core/utils/smartart-color-lists.ts
32670
+ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
32671
+ "srgbClr",
32672
+ "schemeClr",
32673
+ "scrgbClr",
32674
+ "sysClr",
32675
+ "prstClr",
32676
+ "hslClr"
32677
+ ]);
32678
+ var COLOR_METHODS2 = /* @__PURE__ */ new Set(["span", "cycle", "repeat"]);
32679
+ var HUE_DIRECTIONS2 = /* @__PURE__ */ new Set(["cw", "ccw"]);
32680
+ var PRIMARY_LABEL_PRIORITY = ["node0", "node1", "node2", "node3", "node4", "node"];
32681
+ function localNameOf3(key) {
32682
+ const idx = key.indexOf(":");
32683
+ return idx >= 0 ? key.slice(idx + 1) : key;
32684
+ }
32685
+ function parseSmartArtColorListHexes(list, deps) {
32686
+ if (!list) {
32687
+ return [];
32688
+ }
32689
+ const out = [];
32690
+ for (const [key, value] of Object.entries(list)) {
32691
+ if (key.startsWith("@_")) {
32692
+ continue;
32693
+ }
32694
+ const local = localNameOf3(key);
32695
+ if (!COLOR_LOCAL_NAMES.has(local)) {
32696
+ continue;
32697
+ }
32698
+ const nodes = Array.isArray(value) ? value : [value];
32699
+ for (const node of nodes) {
32700
+ if (!node || typeof node !== "object") {
32701
+ continue;
32702
+ }
32703
+ const wrapper = { [`a:${local}`]: node };
32704
+ const hex10 = deps.parseColorChoice(wrapper) ?? deps.resolveScheme(node);
32705
+ if (hex10) {
32706
+ out.push(hex10);
32707
+ }
32708
+ }
32709
+ }
32710
+ return out;
32711
+ }
32712
+ function listInterpolation(list) {
32713
+ if (!list) {
32714
+ return void 0;
32715
+ }
32716
+ const method = String(list["@_meth"] ?? "").trim();
32717
+ const hueDir = String(list["@_hueDir"] ?? "").trim();
32718
+ const meta = {};
32719
+ if (COLOR_METHODS2.has(method)) {
32720
+ meta.method = method;
32721
+ }
32722
+ if (HUE_DIRECTIONS2.has(hueDir)) {
32723
+ meta.hueDirection = hueDir;
32724
+ }
32725
+ return meta.method || meta.hueDirection ? meta : void 0;
32726
+ }
32727
+ function parseLabel(lbl, deps) {
32728
+ const fillList = deps.getChild(lbl, "fillClrLst");
32729
+ const lineList = deps.getChild(lbl, "linClrLst");
32730
+ return {
32731
+ name: String(lbl["@_name"] ?? "").trim(),
32732
+ fill: parseSmartArtColorListHexes(fillList, deps),
32733
+ line: parseSmartArtColorListHexes(lineList, deps),
32734
+ textFill: parseSmartArtColorListHexes(deps.getChild(lbl, "txFillClrLst"), deps),
32735
+ textLine: parseSmartArtColorListHexes(deps.getChild(lbl, "txLinClrLst"), deps),
32736
+ effect: parseSmartArtColorListHexes(deps.getChild(lbl, "effectClrLst"), deps),
32737
+ textEffect: parseSmartArtColorListHexes(deps.getChild(lbl, "txEffectClrLst"), deps),
32738
+ fillInterpolation: listInterpolation(fillList),
32739
+ lineInterpolation: listInterpolation(lineList)
32740
+ };
32741
+ }
32742
+ function selectPrimary(parsed) {
32743
+ const byName = new Map(parsed.map((p) => [p.name, p]));
32744
+ for (const name of PRIMARY_LABEL_PRIORITY) {
32745
+ const candidate = byName.get(name);
32746
+ if (candidate && candidate.fill.length > 0) {
32747
+ return candidate;
32748
+ }
32749
+ }
32750
+ for (const name of PRIMARY_LABEL_PRIORITY) {
32751
+ const candidate = byName.get(name);
32752
+ if (candidate && (candidate.line.length > 0 || candidate.fill.length > 0)) {
32753
+ return candidate;
32754
+ }
32755
+ }
32756
+ return parsed.find((p) => p.fill.length > 0) ?? parsed.find((p) => p.line.length > 0);
32757
+ }
32758
+ function buildSmartArtColorLists(styleLbls, deps) {
32759
+ const parsed = styleLbls.map((lbl) => parseLabel(lbl, deps));
32760
+ const primary = selectPrimary(parsed);
32761
+ let fillColors = primary?.fill ?? [];
32762
+ let lineColors = primary?.line ?? [];
32763
+ if (fillColors.length === 0) {
32764
+ fillColors = parsed.map((p) => p.fill[0]).filter((c) => Boolean(c));
32765
+ }
32766
+ if (lineColors.length === 0) {
32767
+ lineColors = parsed.map((p) => p.line[0]).filter((c) => Boolean(c));
32768
+ }
32769
+ const result = { fillColors, lineColors };
32770
+ if (primary?.textFill.length) {
32771
+ result.textFillColors = primary.textFill;
32772
+ }
32773
+ if (primary?.textLine.length) {
32774
+ result.textLineColors = primary.textLine;
32775
+ }
32776
+ if (primary?.effect.length) {
32777
+ result.effectColors = primary.effect;
32778
+ }
32779
+ if (primary?.textEffect.length) {
32780
+ result.textEffectColors = primary.textEffect;
32781
+ }
32782
+ if (primary?.fillInterpolation) {
32783
+ result.fillInterpolation = primary.fillInterpolation;
32784
+ }
32785
+ if (primary?.lineInterpolation) {
32786
+ result.lineInterpolation = primary.lineInterpolation;
32787
+ }
32788
+ return result;
32789
+ }
32790
+
31905
32791
  // src/core/utils/modern-comment-constants.ts
31906
32792
  var MODERN_COMMENT_NAMESPACE = "http://schemas.microsoft.com/office/powerpoint/2018/8/main";
31907
32793
  var MODERN_COMMENT_RELATIONSHIP = "http://schemas.microsoft.com/office/2018/10/relationships/comments";
@@ -34208,6 +35094,28 @@ function buildGeneratedChartAxis(axId, crossId, pos2, formatting) {
34208
35094
  return axis;
34209
35095
  }
34210
35096
 
35097
+ // src/core/utils/chart-xml-container-map.ts
35098
+ var CONTAINER_MAP = {
35099
+ pie: { tag: "c:pieChart", family: "pie" },
35100
+ pie3D: { tag: "c:pie3DChart", family: "pie" },
35101
+ ofPie: { tag: "c:ofPieChart", family: "ofPie" },
35102
+ doughnut: { tag: "c:doughnutChart", family: "doughnut" },
35103
+ scatter: { tag: "c:scatterChart", family: "scatter" },
35104
+ bubble: { tag: "c:bubbleChart", family: "bubble" },
35105
+ line: { tag: "c:lineChart", family: "line" },
35106
+ line3D: { tag: "c:line3DChart", family: "line" },
35107
+ area: { tag: "c:areaChart", family: "area" },
35108
+ area3D: { tag: "c:area3DChart", family: "area" },
35109
+ radar: { tag: "c:radarChart", family: "radar" },
35110
+ stock: { tag: "c:stockChart", family: "stock" },
35111
+ surface: { tag: "c:surfaceChart", family: "surface" },
35112
+ bar: { tag: "c:barChart", family: "bar" },
35113
+ bar3D: { tag: "c:bar3DChart", family: "bar" }
35114
+ };
35115
+ function resolveChartContainerType(type) {
35116
+ return CONTAINER_MAP[type] ?? { tag: "c:barChart", family: "bar" };
35117
+ }
35118
+
34211
35119
  // src/core/utils/chart-xml-generator.ts
34212
35120
  var NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart";
34213
35121
  var NS_A2 = "http://schemas.openxmlformats.org/drawingml/2006/main";
@@ -34238,29 +35146,6 @@ function strLit(values) {
34238
35146
  }
34239
35147
  };
34240
35148
  }
34241
- function resolveType(type) {
34242
- switch (type) {
34243
- case "pie":
34244
- case "pie3D":
34245
- return { tag: "c:pieChart", family: "pie" };
34246
- case "doughnut":
34247
- return { tag: "c:doughnutChart", family: "doughnut" };
34248
- case "scatter":
34249
- return { tag: "c:scatterChart", family: "scatter" };
34250
- case "bubble":
34251
- return { tag: "c:bubbleChart", family: "bubble" };
34252
- case "line":
34253
- case "line3D":
34254
- return { tag: "c:lineChart", family: "line" };
34255
- case "area":
34256
- case "area3D":
34257
- return { tag: "c:areaChart", family: "area" };
34258
- case "radar":
34259
- return { tag: "c:radarChart", family: "radar" };
34260
- default:
34261
- return { tag: "c:barChart", family: "bar" };
34262
- }
34263
- }
34264
35149
  function fillSpPr(color2, asLine) {
34265
35150
  const h = hex6(color2);
34266
35151
  if (!h) {
@@ -34328,7 +35213,10 @@ function buildChartTypeContainer(chartData, family) {
34328
35213
  } else if (family === "scatter") {
34329
35214
  container["c:scatterStyle"] = { "@_val": "lineMarker" };
34330
35215
  container["c:varyColors"] = { "@_val": "0" };
34331
- } else {
35216
+ } else if (family === "ofPie") {
35217
+ container["c:ofPieType"] = { "@_val": "pie" };
35218
+ container["c:varyColors"] = { "@_val": "1" };
35219
+ } else if (family === "stock" || family === "surface") ; else {
34332
35220
  container["c:varyColors"] = { "@_val": family === "bubble" ? "0" : "1" };
34333
35221
  }
34334
35222
  container["c:ser"] = chartData.series.map(
@@ -34340,12 +35228,13 @@ function buildChartTypeContainer(chartData, family) {
34340
35228
  if (family === "line" && chartData.upDownBars !== void 0) {
34341
35229
  applyChartUpDownBars(container, chartData.upDownBars, (key) => key.replace(/^.*:/u, ""));
34342
35230
  }
34343
- if (family === "bar") {
35231
+ if (family === "bar" || family === "ofPie") {
34344
35232
  container["c:gapWidth"] = { "@_val": "150" };
34345
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34346
- } else if (family === "line" || family === "area" || family === "radar") {
34347
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34348
- } else if (family === "scatter" || family === "bubble") {
35233
+ }
35234
+ if (family === "stock") {
35235
+ container["c:hiLowLines"] = {};
35236
+ }
35237
+ if (family === "bar" || family === "line" || family === "area" || family === "radar" || family === "scatter" || family === "bubble" || family === "stock" || family === "surface") {
34349
35238
  container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34350
35239
  } else if (family === "doughnut") {
34351
35240
  container["c:holeSize"] = { "@_val": "50" };
@@ -34358,7 +35247,8 @@ function buildPlotArea(chartData, tag, family) {
34358
35247
  if (chartData.style) {
34359
35248
  applyChartDataLabelsToXml(plotArea, chartData.style, (key) => key.replace(/^.*:/u, ""));
34360
35249
  }
34361
- if (family !== "pie" && family !== "doughnut" && SCATTER_LIKE.has(chartData.chartType)) {
35250
+ const hasAxes = family !== "pie" && family !== "doughnut" && family !== "ofPie";
35251
+ if (hasAxes && SCATTER_LIKE.has(chartData.chartType)) {
34362
35252
  plotArea["c:valAx"] = [
34363
35253
  buildGeneratedChartAxis(
34364
35254
  CAT_AX_ID,
@@ -34373,7 +35263,7 @@ function buildPlotArea(chartData, tag, family) {
34373
35263
  axisFormatting(chartData, "valAx", VAL_AX_ID, 1)
34374
35264
  )
34375
35265
  ];
34376
- } else if (family !== "pie" && family !== "doughnut") {
35266
+ } else if (hasAxes) {
34377
35267
  const dateAxis = chartData.dateCategories ? axisFormatting(chartData, "dateAx", CAT_AX_ID) : void 0;
34378
35268
  plotArea[dateAxis ? "c:dateAx" : "c:catAx"] = buildGeneratedChartAxis(
34379
35269
  CAT_AX_ID,
@@ -34392,7 +35282,7 @@ function buildPlotArea(chartData, tag, family) {
34392
35282
  return plotArea;
34393
35283
  }
34394
35284
  function buildChartSpaceXml(chartData) {
34395
- const { tag, family } = resolveType(chartData.chartType);
35285
+ const { tag, family } = resolveChartContainerType(chartData.chartType);
34396
35286
  const chart = {};
34397
35287
  if (chartData.title) {
34398
35288
  chart["c:title"] = {
@@ -36324,6 +37214,7 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36324
37214
  let playbackSpeed;
36325
37215
  let trimStartMs;
36326
37216
  let trimEndMs;
37217
+ let embedRId;
36327
37218
  const bookmarks = [];
36328
37219
  const extLst = mediaNode["p:extLst"] ?? cMediaNode["p:extLst"];
36329
37220
  if (extLst) {
@@ -36331,6 +37222,13 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36331
37222
  for (const ext of exts) {
36332
37223
  const p14Media = ext["p14:media"];
36333
37224
  if (p14Media) {
37225
+ if (embedRId === void 0) {
37226
+ const embedRaw = p14Media["@_r:embed"] ?? p14Media["@_embed"];
37227
+ const embedStr = embedRaw === void 0 ? "" : String(embedRaw).trim();
37228
+ if (embedStr.length > 0) {
37229
+ embedRId = embedStr;
37230
+ }
37231
+ }
36334
37232
  const p14Trim = p14Media["p14:trim"];
36335
37233
  if (p14Trim) {
36336
37234
  const st = p14Trim["@_st"];
@@ -36400,7 +37298,8 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36400
37298
  fadeInDuration,
36401
37299
  fadeOutDuration,
36402
37300
  playbackSpeed,
36403
- bookmarks
37301
+ bookmarks,
37302
+ embedRId
36404
37303
  };
36405
37304
  }
36406
37305
 
@@ -36630,6 +37529,12 @@ var PptxHandlerRuntime = class {
36630
37529
  loadedEmbeddedFonts = [];
36631
37530
  /** Typed source metadata for lossless embedded-font list round trips. */
36632
37531
  loadedEmbeddedFontList;
37532
+ /**
37533
+ * View properties parsed from `ppt/viewProps.xml` during load, preserved so
37534
+ * an unmodified load -> save round-trips the typed model and callers that do
37535
+ * not override `saveOptions.viewProperties` still persist the loaded state.
37536
+ */
37537
+ loadedViewProperties;
36633
37538
  /** Map of comment author IDs to display names (from `ppt/commentAuthors.xml`). */
36634
37539
  commentAuthorMap = /* @__PURE__ */ new Map();
36635
37540
  /** Full comment author details keyed by author ID, preserving initials/lastIdx/clrIdx for round-trip. */
@@ -36769,19 +37674,266 @@ var PptxHandlerRuntime = class {
36769
37674
  }
36770
37675
  };
36771
37676
 
37677
+ // src/core/core/runtime/table-style-border-parse.ts
37678
+ var EMU_PER_PIXEL = 9525;
37679
+ var BORDER_SIDES = [
37680
+ "left",
37681
+ "right",
37682
+ "top",
37683
+ "bottom",
37684
+ "insideH",
37685
+ "insideV",
37686
+ "tl2br",
37687
+ "bl2tr"
37688
+ ];
37689
+ function parseSolidFillStyle(solidFill2) {
37690
+ if (!solidFill2) {
37691
+ return void 0;
37692
+ }
37693
+ const schemeClr = solidFill2["a:schemeClr"];
37694
+ if (!schemeClr) {
37695
+ return void 0;
37696
+ }
37697
+ const schemeColor = String(schemeClr["@_val"] || "").trim() || void 0;
37698
+ if (!schemeColor) {
37699
+ return void 0;
37700
+ }
37701
+ const tintRaw = schemeClr["a:tint"];
37702
+ const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
37703
+ const shadeRaw = schemeClr["a:shade"];
37704
+ const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
37705
+ return { schemeColor, tint, shade };
37706
+ }
37707
+ function parseBorderSide(side) {
37708
+ if (!side) {
37709
+ return void 0;
37710
+ }
37711
+ const ln = side["a:ln"];
37712
+ if (!ln) {
37713
+ return void 0;
37714
+ }
37715
+ const border = {};
37716
+ let has = false;
37717
+ if (ln["a:noFill"] !== void 0) {
37718
+ border.noFill = true;
37719
+ has = true;
37720
+ }
37721
+ const widthEmu = parseInt(String(ln["@_w"] || "0"), 10);
37722
+ if (widthEmu > 0) {
37723
+ border.width = Math.max(1, Math.round(widthEmu / EMU_PER_PIXEL));
37724
+ has = true;
37725
+ }
37726
+ const prstDash = ln["a:prstDash"];
37727
+ const dashVal = prstDash ? String(prstDash["@_val"] || "").trim() : "";
37728
+ if (dashVal) {
37729
+ border.dash = dashVal;
37730
+ has = true;
37731
+ }
37732
+ const solidFill2 = ln["a:solidFill"];
37733
+ const fill = parseSolidFillStyle(solidFill2);
37734
+ if (fill) {
37735
+ border.fill = fill;
37736
+ has = true;
37737
+ } else {
37738
+ const srgb = solidFill2?.["a:srgbClr"];
37739
+ const hex10 = srgb ? String(srgb["@_val"] || "").trim() : "";
37740
+ if (hex10) {
37741
+ border.color = hex10.startsWith("#") ? hex10 : `#${hex10}`;
37742
+ has = true;
37743
+ }
37744
+ }
37745
+ return has ? border : void 0;
37746
+ }
37747
+ function parseTableStyleBorders(tcStyle) {
37748
+ const tcBdr = tcStyle?.["a:tcBdr"];
37749
+ if (!tcBdr) {
37750
+ return void 0;
37751
+ }
37752
+ const result = {};
37753
+ let has = false;
37754
+ for (const name of BORDER_SIDES) {
37755
+ const border = parseBorderSide(tcBdr[`a:${name}`]);
37756
+ if (border) {
37757
+ result[name] = border;
37758
+ has = true;
37759
+ }
37760
+ }
37761
+ return has ? result : void 0;
37762
+ }
37763
+
37764
+ // src/core/core/runtime/table-style-fill-parse.ts
37765
+ function toHex3(raw) {
37766
+ const hex10 = String(raw ?? "").trim();
37767
+ if (!hex10) {
37768
+ return void 0;
37769
+ }
37770
+ return hex10.startsWith("#") ? hex10 : `#${hex10}`;
37771
+ }
37772
+ function parseColorChoiceFill(node) {
37773
+ if (!node) {
37774
+ return void 0;
37775
+ }
37776
+ const scheme = parseSolidFillStyle(node);
37777
+ if (scheme) {
37778
+ return scheme;
37779
+ }
37780
+ const srgb = node["a:srgbClr"];
37781
+ const color2 = toHex3(srgb?.["@_val"]);
37782
+ if (!color2) {
37783
+ return void 0;
37784
+ }
37785
+ const fill = { schemeColor: "", color: color2 };
37786
+ const tintRaw = srgb?.["a:tint"];
37787
+ const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
37788
+ if (tint !== void 0) {
37789
+ fill.tint = tint;
37790
+ }
37791
+ const shadeRaw = srgb?.["a:shade"];
37792
+ const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
37793
+ if (shade !== void 0) {
37794
+ fill.shade = shade;
37795
+ }
37796
+ return fill;
37797
+ }
37798
+ function parseGradientFill(gradFill) {
37799
+ const gsLst = gradFill["a:gsLst"];
37800
+ const rawStops = gsLst?.["a:gs"];
37801
+ const gsNodes = Array.isArray(rawStops) ? rawStops : rawStops ? [rawStops] : [];
37802
+ const stops = [];
37803
+ for (const gs of gsNodes) {
37804
+ const fill = parseColorChoiceFill(gs);
37805
+ if (!fill) {
37806
+ continue;
37807
+ }
37808
+ const position2 = (parseInt(String(gs["@_pos"] || "0"), 10) || 0) / 1e3;
37809
+ stops.push({ position: position2, fill });
37810
+ }
37811
+ if (stops.length === 0) {
37812
+ return void 0;
37813
+ }
37814
+ const lin = gradFill["a:lin"];
37815
+ if (lin) {
37816
+ const angRaw = parseInt(String(lin["@_ang"] || "0"), 10) || 0;
37817
+ const angle = (angRaw / 6e4 % 360 + 360) % 360;
37818
+ return { stops, angle, type: "linear" };
37819
+ }
37820
+ if (gradFill["a:path"] !== void 0) {
37821
+ return { stops, type: "radial" };
37822
+ }
37823
+ return { stops, type: "linear" };
37824
+ }
37825
+ function parsePatternFill(pattFill) {
37826
+ const preset = String(pattFill["@_prst"] || "").trim();
37827
+ if (!preset) {
37828
+ return void 0;
37829
+ }
37830
+ const pattern = { preset };
37831
+ const foreground = parseColorChoiceFill(pattFill["a:fgClr"]);
37832
+ if (foreground) {
37833
+ pattern.foreground = foreground;
37834
+ }
37835
+ const background = parseColorChoiceFill(pattFill["a:bgClr"]);
37836
+ if (background) {
37837
+ pattern.background = background;
37838
+ }
37839
+ return pattern;
37840
+ }
37841
+ function parseTableStyleSectionFill(section) {
37842
+ if (!section) {
37843
+ return void 0;
37844
+ }
37845
+ const tcStyle = section["a:tcStyle"];
37846
+ const fillWrap = tcStyle?.["a:fill"];
37847
+ if (!fillWrap) {
37848
+ return void 0;
37849
+ }
37850
+ if (fillWrap["a:noFill"] !== void 0) {
37851
+ return { schemeColor: "", noFill: true };
37852
+ }
37853
+ const solid = fillWrap["a:solidFill"];
37854
+ if (solid) {
37855
+ return parseColorChoiceFill(solid);
37856
+ }
37857
+ const grad = fillWrap["a:gradFill"];
37858
+ if (grad) {
37859
+ const gradient = parseGradientFill(grad);
37860
+ if (gradient) {
37861
+ return { schemeColor: "", gradient };
37862
+ }
37863
+ }
37864
+ const patt = fillWrap["a:pattFill"];
37865
+ if (patt) {
37866
+ const pattern = parsePatternFill(patt);
37867
+ if (pattern) {
37868
+ return { schemeColor: "", pattern };
37869
+ }
37870
+ }
37871
+ return void 0;
37872
+ }
37873
+ function parseTableStyleSectionText(section) {
37874
+ const tcTxStyle = section?.["a:tcTxStyle"];
37875
+ if (!tcTxStyle) {
37876
+ return void 0;
37877
+ }
37878
+ const result = {};
37879
+ let hasProps = false;
37880
+ if (tcTxStyle["@_b"] === "on") {
37881
+ result.bold = true;
37882
+ hasProps = true;
37883
+ }
37884
+ if (tcTxStyle["@_i"] === "on") {
37885
+ result.italic = true;
37886
+ hasProps = true;
37887
+ }
37888
+ const underline = String(tcTxStyle["@_u"] || "").trim();
37889
+ if (underline && underline !== "none") {
37890
+ result.underline = true;
37891
+ hasProps = true;
37892
+ }
37893
+ const font = tcTxStyle["a:font"];
37894
+ const face = font ? String(font["@_typeface"] || "").trim() : "";
37895
+ if (face) {
37896
+ result.fontFace = face;
37897
+ hasProps = true;
37898
+ }
37899
+ const fontRef = tcTxStyle["a:fontRef"];
37900
+ const idx = fontRef ? String(fontRef["@_idx"] || "").trim() : "";
37901
+ if (idx) {
37902
+ result.fontRefIdx = idx;
37903
+ hasProps = true;
37904
+ }
37905
+ const schemeClr = fontRef?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
37906
+ if (schemeClr) {
37907
+ const val = String(schemeClr["@_val"] || "").trim();
37908
+ if (val) {
37909
+ result.fontSchemeColor = val;
37910
+ hasProps = true;
37911
+ const tintNode = schemeClr["a:tint"];
37912
+ if (tintNode) {
37913
+ result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
37914
+ }
37915
+ const shadeNode = schemeClr["a:shade"];
37916
+ if (shadeNode) {
37917
+ result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
37918
+ }
37919
+ }
37920
+ } else {
37921
+ const srgb = fontRef?.["a:srgbClr"] ?? tcTxStyle["a:srgbClr"];
37922
+ const hex10 = toHex3(srgb?.["@_val"]);
37923
+ if (hex10) {
37924
+ result.fontColor = hex10;
37925
+ hasProps = true;
37926
+ }
37927
+ }
37928
+ return hasProps ? result : void 0;
37929
+ }
37930
+
36772
37931
  // src/core/core/runtime/PptxHandlerRuntimeTableStyles.ts
36773
37932
  var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
36774
37933
  /**
36775
- * Export slides to a raster/vector format.
36776
- *
36777
- * This is a stub that signals export intent. Actual rendering requires a
36778
- * platform-specific canvas or PDF library (e.g. Puppeteer, node-canvas,
36779
- * pdfkit). Host applications should override or extend this method with
36780
- * their own rendering pipeline.
36781
- *
36782
- * @param _slides The slides to export.
36783
- * @param _options Export options (format, DPI, slide indices, etc.).
36784
- * @returns A map of slide index → exported binary data.
37934
+ * Export slides to a raster/vector format. This is a stub that signals
37935
+ * export intent; actual rendering requires a platform-specific canvas or
37936
+ * PDF backend that host applications wire in by overriding this method.
36785
37937
  */
36786
37938
  async exportSlides(slides, options) {
36787
37939
  this.compatibilityService.reportWarning({
@@ -36846,77 +37998,26 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
36846
37998
  }
36847
37999
  /**
36848
38000
  * Extract fill information from a table style section element
36849
- * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`).
38001
+ * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`). Handles scheme + sRGB
38002
+ * solids, gradients, preset patterns, and `a:noFill` (issue #95).
36850
38003
  */
36851
38004
  extractTableStyleSectionFill(section) {
36852
- if (!section) {
36853
- return void 0;
36854
- }
36855
- const tcStyle = section["a:tcStyle"];
36856
- if (!tcStyle) {
36857
- return void 0;
36858
- }
36859
- const fill = tcStyle["a:fill"];
36860
- if (!fill) {
36861
- return void 0;
36862
- }
36863
- const solidFill2 = fill["a:solidFill"];
36864
- if (!solidFill2) {
36865
- return void 0;
36866
- }
36867
- const schemeClr = solidFill2["a:schemeClr"];
36868
- if (!schemeClr) {
36869
- return void 0;
36870
- }
36871
- const schemeColor = String(schemeClr["@_val"] || "").trim() || void 0;
36872
- if (!schemeColor) {
36873
- return void 0;
36874
- }
36875
- const tintRaw = schemeClr["a:tint"];
36876
- const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
36877
- const shadeRaw = schemeClr["a:shade"];
36878
- const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
36879
- return { schemeColor, tint, shade };
38005
+ return parseTableStyleSectionFill(section);
38006
+ }
38007
+ /**
38008
+ * Extract border styling from a table style section's
38009
+ * `a:tcStyle/a:tcBdr` (per-side line width, dash, and colour).
38010
+ */
38011
+ extractTableStyleSectionBorders(section) {
38012
+ return parseTableStyleBorders(section?.["a:tcStyle"]);
36880
38013
  }
36881
38014
  /**
36882
- * Extract text properties from a:tcTxStyle in a table style section.
38015
+ * Extract text properties from `a:tcTxStyle` in a table style section.
38016
+ * Captures bold/italic/underline, typeface, font-collection index, and the
38017
+ * font colour (scheme or sRGB) (issue #95).
36883
38018
  */
36884
38019
  extractTableStyleSectionText(section) {
36885
- if (!section) {
36886
- return void 0;
36887
- }
36888
- const tcTxStyle = section["a:tcTxStyle"];
36889
- if (!tcTxStyle) {
36890
- return void 0;
36891
- }
36892
- const result = {};
36893
- let hasProps = false;
36894
- if (tcTxStyle["@_b"] === "on") {
36895
- result.bold = true;
36896
- hasProps = true;
36897
- }
36898
- if (tcTxStyle["@_i"] === "on") {
36899
- result.italic = true;
36900
- hasProps = true;
36901
- }
36902
- const fontClr = tcTxStyle["a:fontRef"];
36903
- const schemeClr = fontClr?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
36904
- if (schemeClr) {
36905
- const val = String(schemeClr["@_val"] || "").trim();
36906
- if (val) {
36907
- result.fontSchemeColor = val;
36908
- hasProps = true;
36909
- const tintNode = schemeClr["a:tint"];
36910
- if (tintNode) {
36911
- result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
36912
- }
36913
- const shadeNode = schemeClr["a:shade"];
36914
- if (shadeNode) {
36915
- result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
36916
- }
36917
- }
36918
- }
36919
- return hasProps ? result : void 0;
38020
+ return parseTableStyleSectionText(section);
36920
38021
  }
36921
38022
  ensureArray(val) {
36922
38023
  if (!val) {
@@ -37023,6 +38124,15 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37023
38124
  textProps[`${name}Text`] = text2;
37024
38125
  }
37025
38126
  }
38127
+ const borderProps = {};
38128
+ for (const name of sectionNames) {
38129
+ const borders = this.extractTableStyleSectionBorders(
38130
+ style[`a:${name}`]
38131
+ );
38132
+ if (borders) {
38133
+ borderProps[`${name}Borders`] = borders;
38134
+ }
38135
+ }
37026
38136
  const entry = {
37027
38137
  styleId,
37028
38138
  styleName,
@@ -37041,7 +38151,8 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37041
38151
  ...swCellFill ? { swCellFill } : {},
37042
38152
  ...neCellFill ? { neCellFill } : {},
37043
38153
  ...nwCellFill ? { nwCellFill } : {},
37044
- ...textProps
38154
+ ...textProps,
38155
+ ...borderProps
37045
38156
  };
37046
38157
  map[styleId] = entry;
37047
38158
  }
@@ -37586,6 +38697,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37586
38697
  );
37587
38698
  const trimStartMs = timing.trimStartMs ?? extData.trimStartMs;
37588
38699
  const trimEndMs = timing.trimEndMs ?? extData.trimEndMs;
38700
+ const mediaEmbedPath = extData.embedRId ? this.resolveRelationshipTarget(slidePath, extData.embedRId) : void 0;
37589
38701
  result.set(shapeId, {
37590
38702
  trimStartMs: trimStartMs !== void 0 && !isNaN(trimStartMs) ? trimStartMs : void 0,
37591
38703
  trimEndMs: trimEndMs !== void 0 && !isNaN(trimEndMs) ? trimEndMs : void 0,
@@ -37599,7 +38711,8 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37599
38711
  playAcrossSlides: timing.playAcrossSlides || void 0,
37600
38712
  hideWhenNotPlaying: hideWhenNotPlaying || void 0,
37601
38713
  bookmarks: extData.bookmarks.length > 0 ? extData.bookmarks : void 0,
37602
- playbackSpeed: extData.playbackSpeed
38714
+ playbackSpeed: extData.playbackSpeed,
38715
+ mediaEmbedPath
37603
38716
  });
37604
38717
  }
37605
38718
  }
@@ -37775,6 +38888,10 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
37775
38888
  if (!timing) {
37776
38889
  continue;
37777
38890
  }
38891
+ if (timing.mediaEmbedPath && (typeof el.mediaPath !== "string" || el.mediaPath.length === 0)) {
38892
+ el.mediaPath = timing.mediaEmbedPath;
38893
+ el.mediaMimeType = this.getImageMimeType(timing.mediaEmbedPath);
38894
+ }
37778
38895
  if (timing.trimStartMs !== void 0) {
37779
38896
  el.trimStartMs = timing.trimStartMs;
37780
38897
  }
@@ -38781,7 +39898,7 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
38781
39898
  }
38782
39899
  }
38783
39900
  async reconcilePresentationSlidesForSave(params) {
38784
- await this.presentationSlidesReconciler.reconcile({
39901
+ return await this.presentationSlidesReconciler.reconcile({
38785
39902
  ...params,
38786
39903
  zip: this.zip,
38787
39904
  parser: this.parser,
@@ -38852,6 +39969,15 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
38852
39969
  if (align === "justify") {
38853
39970
  return "just";
38854
39971
  }
39972
+ if (align === "justLow") {
39973
+ return "justLow";
39974
+ }
39975
+ if (align === "dist") {
39976
+ return "dist";
39977
+ }
39978
+ if (align === "thaiDist") {
39979
+ return "thaiDist";
39980
+ }
38855
39981
  return void 0;
38856
39982
  }
38857
39983
  pixelsToPoints(px) {
@@ -39065,6 +40191,31 @@ function applyFontMetadata(fontNode, panose, pitchFamily, charset) {
39065
40191
  }
39066
40192
  return fontNode;
39067
40193
  }
40194
+ function buildUnderlineLineXml(line2) {
40195
+ const uln = {};
40196
+ if (typeof line2.widthEmu === "number" && Number.isFinite(line2.widthEmu)) {
40197
+ uln["@_w"] = String(Math.round(line2.widthEmu));
40198
+ }
40199
+ if (line2.compound) {
40200
+ uln["@_cmpd"] = line2.compound;
40201
+ }
40202
+ if (line2.cap) {
40203
+ uln["@_cap"] = line2.cap;
40204
+ }
40205
+ if (line2.algn) {
40206
+ uln["@_algn"] = line2.algn;
40207
+ }
40208
+ if (line2.prstDash) {
40209
+ uln["a:prstDash"] = { "@_val": line2.prstDash };
40210
+ }
40211
+ if (line2.headEndXml) {
40212
+ uln["a:headEnd"] = line2.headEndXml;
40213
+ }
40214
+ if (line2.tailEndXml) {
40215
+ uln["a:tailEnd"] = line2.tailEndXml;
40216
+ }
40217
+ return uln;
40218
+ }
39068
40219
  var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime11 {
39069
40220
  createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId) {
39070
40221
  const runProps = {
@@ -39085,6 +40236,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39085
40236
  }
39086
40237
  if (style.underline) {
39087
40238
  runProps["@_u"] = style.underlineStyle || "sng";
40239
+ } else if (style.underlineExplicitNone) {
40240
+ runProps["@_u"] = "none";
39088
40241
  }
39089
40242
  if (style.strikethrough !== void 0) {
39090
40243
  runProps["@_strike"] = style.strikethrough ? style.strikeType || "sngStrike" : "noStrike";
@@ -39100,6 +40253,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39100
40253
  }
39101
40254
  if (style.textCaps && style.textCaps !== "none") {
39102
40255
  runProps["@_cap"] = style.textCaps;
40256
+ } else if (style.textCapsExplicitNone) {
40257
+ runProps["@_cap"] = "none";
39103
40258
  }
39104
40259
  if (style.kumimoji !== void 0) {
39105
40260
  runProps["@_kumimoji"] = style.kumimoji ? "1" : "0";
@@ -39208,13 +40363,21 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39208
40363
  runProps["a:effectDag"] = style.textEffectDagXml;
39209
40364
  }
39210
40365
  if (style.highlightColor) {
39211
- runProps["a:highlight"] = {
39212
- "a:srgbClr": {
39213
- "@_val": style.highlightColor.replace("#", "")
39214
- }
39215
- };
40366
+ const resolvedHighlight = style.highlightColorXml ? this.parseColor(style.highlightColorXml) : void 0;
40367
+ runProps["a:highlight"] = serializeColorChoice(
40368
+ style.highlightColorXml,
40369
+ resolvedHighlight,
40370
+ style.highlightColor
40371
+ );
40372
+ }
40373
+ if (style.underlineLineFollowsText) {
40374
+ runProps["a:uLnTx"] = {};
40375
+ } else if (style.underlineLine) {
40376
+ runProps["a:uLn"] = buildUnderlineLineXml(style.underlineLine);
39216
40377
  }
39217
- if (style.underline && style.underlineColor) {
40378
+ if (style.underlineFillFollowsText) {
40379
+ runProps["a:uFillTx"] = {};
40380
+ } else if (style.underline && style.underlineColor) {
39218
40381
  runProps["a:uFill"] = {
39219
40382
  "a:solidFill": {
39220
40383
  "a:srgbClr": {
@@ -39223,21 +40386,28 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39223
40386
  }
39224
40387
  };
39225
40388
  }
39226
- if (style.fontFamily) {
40389
+ const latinFace = style.latinFontThemeToken ?? style.fontFamily;
40390
+ if (latinFace) {
39227
40391
  runProps["a:latin"] = applyFontMetadata(
39228
- { "@_typeface": style.fontFamily },
40392
+ { "@_typeface": latinFace },
39229
40393
  style.latinFontPanose,
39230
40394
  style.latinFontPitchFamily,
39231
40395
  style.latinFontCharset
39232
40396
  );
40397
+ }
40398
+ const eastAsiaFace = style.eastAsiaFontThemeToken ?? style.eastAsiaFont;
40399
+ if (eastAsiaFace) {
39233
40400
  runProps["a:ea"] = applyFontMetadata(
39234
- { "@_typeface": style.eastAsiaFont || style.fontFamily },
40401
+ { "@_typeface": eastAsiaFace },
39235
40402
  style.eastAsiaFontPanose,
39236
40403
  style.eastAsiaFontPitchFamily,
39237
40404
  style.eastAsiaFontCharset
39238
40405
  );
40406
+ }
40407
+ const complexScriptFace = style.complexScriptFontThemeToken ?? style.complexScriptFont;
40408
+ if (complexScriptFace) {
39239
40409
  runProps["a:cs"] = applyFontMetadata(
39240
- { "@_typeface": style.complexScriptFont || style.fontFamily },
40410
+ { "@_typeface": complexScriptFace },
39241
40411
  style.complexScriptFontPanose,
39242
40412
  style.complexScriptFontPitchFamily,
39243
40413
  style.complexScriptFontCharset
@@ -39287,12 +40457,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39287
40457
  if (mouseOverTarget.length > 0) {
39288
40458
  const mouseOverRelId = resolveHyperlinkRelationshipId(mouseOverTarget);
39289
40459
  if (mouseOverRelId) {
39290
- runProps["a:hlinkMouseOver"] = {
39291
- "@_r:id": mouseOverRelId
39292
- };
40460
+ const mouseOverNode = { "@_r:id": mouseOverRelId };
40461
+ if (style.hyperlinkMouseOverSoundXml && typeof style.hyperlinkMouseOverSoundXml === "object") {
40462
+ mouseOverNode["a:snd"] = style.hyperlinkMouseOverSoundXml;
40463
+ }
40464
+ runProps["a:hlinkMouseOver"] = mouseOverNode;
39293
40465
  }
39294
40466
  }
39295
40467
  }
40468
+ if (style.runPropertiesExtLstXml && typeof style.runPropertiesExtLstXml === "object") {
40469
+ runProps["a:extLst"] = style.runPropertiesExtLstXml;
40470
+ }
39296
40471
  return runProps;
39297
40472
  }
39298
40473
  applyHyperlinkExtraAttrs(hlinkNode, style) {
@@ -39311,22 +40486,26 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39311
40486
  if (style.hyperlinkEndSound !== void 0) {
39312
40487
  hlinkNode["@_endSnd"] = style.hyperlinkEndSound ? "1" : "0";
39313
40488
  }
40489
+ if (style.hyperlinkSoundXml && typeof style.hyperlinkSoundXml === "object") {
40490
+ hlinkNode["a:snd"] = style.hyperlinkSoundXml;
40491
+ }
39314
40492
  }
39315
40493
  };
39316
40494
 
39317
40495
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphs.ts
39318
40496
  var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39319
40497
  createParagraphsFromTextContent(text2, textStyle, textSegments, resolveHyperlinkRelationshipId) {
39320
- const paragraphAlign = this.textAlignToDrawingValue(textStyle?.align);
39321
- const spacing = {
39322
- spacingBefore: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingBefore),
39323
- spacingAfter: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingAfter),
39324
- lineSpacing: this.createLineSpacingXmlFromMultiplier(textStyle?.lineSpacing),
39325
- lineSpacingExactPt: textStyle?.lineSpacingExactPt
39326
- };
39327
- const createParagraph = (runs, bulletInfo, level, endParaRunProperties) => {
40498
+ const createParagraph = (runs, bulletInfo, level, endParaRunProperties, paragraphProperties2) => {
40499
+ const effectiveStyle = paragraphProperties2 ? { ...textStyle, ...paragraphProperties2 } : textStyle;
40500
+ const paragraphAlign = this.textAlignToDrawingValue(effectiveStyle?.align);
40501
+ const spacing = {
40502
+ spacingBefore: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingBefore),
40503
+ spacingAfter: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingAfter),
40504
+ lineSpacing: this.createLineSpacingXmlFromMultiplier(effectiveStyle?.lineSpacing),
40505
+ lineSpacingExactPt: effectiveStyle?.lineSpacingExactPt
40506
+ };
39328
40507
  const paragraphProps = buildParagraphPropertiesXml(
39329
- textStyle,
40508
+ effectiveStyle,
39330
40509
  paragraphAlign,
39331
40510
  bulletInfo,
39332
40511
  spacing,
@@ -39338,12 +40517,22 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39338
40517
  "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39339
40518
  "a:t": runText
39340
40519
  });
39341
- const createFieldRun = (runText, style, fieldType, fieldGuid) => ({
39342
- "@_type": fieldType,
39343
- ...fieldGuid ? { "@_id": fieldGuid } : {},
39344
- "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39345
- "a:t": runText
39346
- });
40520
+ const createFieldRun = (runText, style, fieldType, fieldGuid, fieldGuidAttr, fieldParagraphPropertiesXml) => {
40521
+ const fld = { "@_type": fieldType };
40522
+ if (fieldGuid) {
40523
+ if (fieldGuidAttr === "uuid") {
40524
+ fld["@_uuid"] = fieldGuid;
40525
+ } else {
40526
+ fld["@_id"] = fieldGuid;
40527
+ }
40528
+ }
40529
+ fld["a:rPr"] = this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId);
40530
+ if (fieldParagraphPropertiesXml && typeof fieldParagraphPropertiesXml === "object") {
40531
+ fld["a:pPr"] = fieldParagraphPropertiesXml;
40532
+ }
40533
+ fld["a:t"] = runText;
40534
+ return fld;
40535
+ };
39347
40536
  const createRubyRun = (segment, style) => {
39348
40537
  const rubyPr = {};
39349
40538
  if (segment.rubyAlignment) {
@@ -39382,17 +40571,27 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39382
40571
  let currentBulletInfo;
39383
40572
  let currentLevel;
39384
40573
  let currentEndParaRunProperties;
40574
+ let currentParagraphProperties;
40575
+ let capturedParagraphMeta = false;
39385
40576
  const pushParagraph = () => {
39386
40577
  if (currentRuns.length === 0) {
39387
40578
  currentRuns.push(createRun("", textStyle));
39388
40579
  }
39389
40580
  paragraphs.push(
39390
- createParagraph(currentRuns, currentBulletInfo, currentLevel, currentEndParaRunProperties)
40581
+ createParagraph(
40582
+ currentRuns,
40583
+ currentBulletInfo,
40584
+ currentLevel,
40585
+ currentEndParaRunProperties,
40586
+ currentParagraphProperties
40587
+ )
39391
40588
  );
39392
40589
  currentRuns = [];
39393
40590
  currentBulletInfo = void 0;
39394
40591
  currentLevel = void 0;
39395
40592
  currentEndParaRunProperties = void 0;
40593
+ currentParagraphProperties = void 0;
40594
+ capturedParagraphMeta = false;
39396
40595
  };
39397
40596
  if (textSegments && textSegments.length > 0) {
39398
40597
  const uniformSegmentOverrides = computeUniformSegmentOverrides(textStyle, textSegments);
@@ -39402,7 +40601,7 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39402
40601
  ...segment.style,
39403
40602
  ...uniformSegmentOverrides
39404
40603
  };
39405
- if (currentRuns.length === 0) {
40604
+ if (!capturedParagraphMeta) {
39406
40605
  if (segment.bulletInfo) {
39407
40606
  currentBulletInfo = segment.bulletInfo;
39408
40607
  }
@@ -39412,6 +40611,10 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39412
40611
  if (segment.endParaRunProperties) {
39413
40612
  currentEndParaRunProperties = segment.endParaRunProperties;
39414
40613
  }
40614
+ if (segment.paragraphProperties) {
40615
+ currentParagraphProperties = segment.paragraphProperties;
40616
+ }
40617
+ capturedParagraphMeta = true;
39415
40618
  }
39416
40619
  if (segment.isLineBreak) {
39417
40620
  const brNode = {};
@@ -39446,7 +40649,9 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39446
40649
  linePart,
39447
40650
  segmentStyle,
39448
40651
  segment.fieldType,
39449
- segment.fieldGuid
40652
+ segment.fieldGuid,
40653
+ segment.fieldGuidAttr,
40654
+ segment.fieldParagraphPropertiesXml
39450
40655
  );
39451
40656
  fieldRun.__isField = true;
39452
40657
  currentRuns.push(fieldRun);
@@ -39906,6 +41111,16 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39906
41111
  const chOffY = 0;
39907
41112
  const chExtCx = extCx;
39908
41113
  const chExtCy = extCy;
41114
+ const xfrmAttrs = {};
41115
+ if (typeof group.rotation === "number" && group.rotation !== 0) {
41116
+ xfrmAttrs["@_rot"] = String(Math.round(group.rotation * 6e4));
41117
+ }
41118
+ if (group.flipHorizontal) {
41119
+ xfrmAttrs["@_flipH"] = "1";
41120
+ }
41121
+ if (group.flipVertical) {
41122
+ xfrmAttrs["@_flipV"] = "1";
41123
+ }
39909
41124
  const grpXml = {
39910
41125
  "p:nvGrpSpPr": {
39911
41126
  "p:cNvPr": { "@_id": "0", "@_name": group.id },
@@ -39914,6 +41129,7 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39914
41129
  },
39915
41130
  "p:grpSpPr": {
39916
41131
  "a:xfrm": {
41132
+ ...xfrmAttrs,
39917
41133
  "a:off": {
39918
41134
  "@_x": String(offX),
39919
41135
  "@_y": String(offY)
@@ -40200,7 +41416,95 @@ var PptxHandlerRuntime16 = class extends PptxHandlerRuntime15 {
40200
41416
  };
40201
41417
 
40202
41418
  // src/core/core/runtime/PptxHandlerRuntimeTextStyleUtils.ts
41419
+ var SCRIPT_CANDIDATES = {
41420
+ cjk: ["Hans", "Hant", "Jpan", "Hang"],
41421
+ kana: ["Jpan", "Hans", "Hant"],
41422
+ hangul: ["Hang"],
41423
+ arabic: ["Arab"],
41424
+ hebrew: ["Hebr"],
41425
+ thai: ["Thai"]
41426
+ };
41427
+ function aggregateFontScriptOverrides(perPathMap) {
41428
+ const aggregate = {};
41429
+ for (const overrides of perPathMap.values()) {
41430
+ for (const [script, typeface] of Object.entries(overrides)) {
41431
+ if (!(script in aggregate)) {
41432
+ aggregate[script] = typeface;
41433
+ }
41434
+ }
41435
+ }
41436
+ return aggregate;
41437
+ }
41438
+ function detectDominantScript(text2) {
41439
+ const counts = {};
41440
+ for (const ch of text2) {
41441
+ const code = ch.codePointAt(0) ?? 0;
41442
+ let cat;
41443
+ if (code >= 4352 && code <= 4607) {
41444
+ cat = "hangul";
41445
+ } else if (code >= 44032 && code <= 55215) {
41446
+ cat = "hangul";
41447
+ } else if (code >= 12352 && code <= 12543) {
41448
+ cat = "kana";
41449
+ } else if (code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 63744 && code <= 64255) {
41450
+ cat = "cjk";
41451
+ } else if (code >= 1536 && code <= 1791) {
41452
+ cat = "arabic";
41453
+ } else if (code >= 1424 && code <= 1535) {
41454
+ cat = "hebrew";
41455
+ } else if (code >= 3584 && code <= 3711) {
41456
+ cat = "thai";
41457
+ }
41458
+ if (cat) {
41459
+ counts[cat] = (counts[cat] ?? 0) + 1;
41460
+ }
41461
+ }
41462
+ let best;
41463
+ let bestCount = 0;
41464
+ for (const [cat, count] of Object.entries(counts)) {
41465
+ if (count > bestCount) {
41466
+ best = cat;
41467
+ bestCount = count;
41468
+ }
41469
+ }
41470
+ return best;
41471
+ }
40203
41472
  var PptxHandlerRuntime17 = class extends PptxHandlerRuntime16 {
41473
+ /**
41474
+ * Resolve the automatic per-script fallback face for a run's text from the
41475
+ * theme's `<a:font script="...">` overrides (#83). Body (minor) fonts win
41476
+ * over heading (major) fonts. Returns `undefined` when the deck declares no
41477
+ * script overrides or the text needs no fallback.
41478
+ */
41479
+ resolveScriptFallbackFont(text2) {
41480
+ if (!text2) {
41481
+ return void 0;
41482
+ }
41483
+ if (this.masterThemeMinorFontScripts.size === 0 && this.masterThemeMajorFontScripts.size === 0) {
41484
+ return void 0;
41485
+ }
41486
+ const category = detectDominantScript(text2);
41487
+ if (!category) {
41488
+ return void 0;
41489
+ }
41490
+ const candidates = SCRIPT_CANDIDATES[category];
41491
+ if (!candidates) {
41492
+ return void 0;
41493
+ }
41494
+ const minor = aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
41495
+ for (const key of candidates) {
41496
+ if (minor[key]) {
41497
+ return minor[key];
41498
+ }
41499
+ }
41500
+ const major = aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
41501
+ for (const key of candidates) {
41502
+ if (major[key]) {
41503
+ return major[key];
41504
+ }
41505
+ }
41506
+ return void 0;
41507
+ }
40204
41508
  textStylesEqual(left, right) {
40205
41509
  const keys = [
40206
41510
  "fontFamily",
@@ -40361,6 +41665,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40361
41665
  const esVal = String(endSnd).trim().toLowerCase();
40362
41666
  style.hyperlinkEndSound = esVal === "1" || esVal === "true";
40363
41667
  }
41668
+ const clickSnd = hyperlinkNode["a:snd"];
41669
+ if (clickSnd && typeof clickSnd === "object") {
41670
+ style.hyperlinkSoundXml = clickSnd;
41671
+ }
40364
41672
  }
40365
41673
  const actionStr = String(hyperlinkNode?.["@_action"] || "").trim();
40366
41674
  if (actionStr) {
@@ -40390,6 +41698,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40390
41698
  } else {
40391
41699
  style.hyperlinkMouseOver = mouseOverRelId;
40392
41700
  }
41701
+ const mouseOverSnd = hlinkMouseOver["a:snd"];
41702
+ if (mouseOverSnd && typeof mouseOverSnd === "object") {
41703
+ style.hyperlinkMouseOverSoundXml = mouseOverSnd;
41704
+ }
40393
41705
  }
40394
41706
  }
40395
41707
  }
@@ -40616,6 +41928,8 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40616
41928
  if (rawU.length > 0 && rawU !== "none") {
40617
41929
  style.underlineStyle = rawU;
40618
41930
  }
41931
+ } else if (underlineToken === "none") {
41932
+ style.underlineExplicitNone = true;
40619
41933
  }
40620
41934
  }
40621
41935
  const uFill = runProperties2["a:uFill"];
@@ -40627,6 +41941,46 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40627
41941
  style.underlineColor = underlineColor;
40628
41942
  }
40629
41943
  }
41944
+ if (uLn) {
41945
+ const line2 = {};
41946
+ const widthEmu = Number.parseInt(String(uLn["@_w"] ?? ""), 10);
41947
+ if (Number.isFinite(widthEmu)) {
41948
+ line2.widthEmu = widthEmu;
41949
+ }
41950
+ const compound = String(uLn["@_cmpd"] ?? "").trim();
41951
+ if (compound) {
41952
+ line2.compound = compound;
41953
+ }
41954
+ const cap = String(uLn["@_cap"] ?? "").trim();
41955
+ if (cap) {
41956
+ line2.cap = cap;
41957
+ }
41958
+ const algn = String(uLn["@_algn"] ?? "").trim();
41959
+ if (algn) {
41960
+ line2.algn = algn;
41961
+ }
41962
+ const prstDash = String(uLn["a:prstDash"]?.["@_val"] ?? "").trim();
41963
+ if (prstDash) {
41964
+ line2.prstDash = prstDash;
41965
+ }
41966
+ const headEnd = uLn["a:headEnd"];
41967
+ if (headEnd && typeof headEnd === "object") {
41968
+ line2.headEndXml = headEnd;
41969
+ }
41970
+ const tailEnd = uLn["a:tailEnd"];
41971
+ if (tailEnd && typeof tailEnd === "object") {
41972
+ line2.tailEndXml = tailEnd;
41973
+ }
41974
+ if (Object.keys(line2).length > 0) {
41975
+ style.underlineLine = line2;
41976
+ }
41977
+ }
41978
+ if (runProperties2["a:uLnTx"] !== void 0) {
41979
+ style.underlineLineFollowsText = true;
41980
+ }
41981
+ if (runProperties2["a:uFillTx"] !== void 0) {
41982
+ style.underlineFillFollowsText = true;
41983
+ }
40630
41984
  if (runProperties2["@_strike"] !== void 0) {
40631
41985
  const strikeToken = String(runProperties2["@_strike"] || "").trim().toLowerCase();
40632
41986
  style.strikethrough = strikeToken.length > 0 && strikeToken !== "nostrike" && strikeToken !== "none" && strikeToken !== "0" && strikeToken !== "false";
@@ -40670,10 +42024,15 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40670
42024
  }
40671
42025
  }
40672
42026
  if (runProperties2["a:highlight"]) {
40673
- const highlightHex = this.parseColor(xmlChild(runProperties2, "a:highlight"));
42027
+ const highlightNode = xmlChild(runProperties2, "a:highlight");
42028
+ const highlightHex = this.parseColor(highlightNode);
40674
42029
  if (highlightHex) {
40675
42030
  style.highlightColor = highlightHex;
40676
42031
  }
42032
+ const highlightXml = extractColorChoiceXml(highlightNode);
42033
+ if (highlightXml) {
42034
+ style.highlightColorXml = highlightXml;
42035
+ }
40677
42036
  }
40678
42037
  const textFillVariants = this.extractTextFillVariants(runProperties2);
40679
42038
  if (textFillVariants.textFillGradient) {
@@ -40694,16 +42053,28 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40694
42053
  const latin = xmlChild(runProperties2, "a:latin");
40695
42054
  const eastAsian = xmlChild(runProperties2, "a:ea");
40696
42055
  const complexScript = xmlChild(runProperties2, "a:cs");
40697
- const chosenTypeface = xmlAttr(latin, "typeface") || xmlAttr(eastAsian, "typeface") || xmlAttr(complexScript, "typeface");
42056
+ const latinTypefaceToken = xmlAttr(latin, "typeface");
42057
+ const eaTypefaceToken = xmlAttr(eastAsian, "typeface");
42058
+ const csTypefaceToken = xmlAttr(complexScript, "typeface");
42059
+ const chosenTypeface = latinTypefaceToken || eaTypefaceToken || csTypefaceToken;
40698
42060
  const resolvedTypeface = this.resolveThemeTypeface(chosenTypeface);
40699
42061
  if (resolvedTypeface) {
40700
42062
  style.fontFamily = resolvedTypeface;
40701
42063
  }
40702
- const eaTypeface = this.resolveThemeTypeface(xmlAttr(eastAsian, "typeface"));
42064
+ if (latinTypefaceToken && latinTypefaceToken.startsWith("+")) {
42065
+ style.latinFontThemeToken = latinTypefaceToken;
42066
+ }
42067
+ if (eaTypefaceToken && eaTypefaceToken.startsWith("+")) {
42068
+ style.eastAsiaFontThemeToken = eaTypefaceToken;
42069
+ }
42070
+ if (csTypefaceToken && csTypefaceToken.startsWith("+")) {
42071
+ style.complexScriptFontThemeToken = csTypefaceToken;
42072
+ }
42073
+ const eaTypeface = this.resolveThemeTypeface(eaTypefaceToken);
40703
42074
  if (eaTypeface) {
40704
42075
  style.eastAsiaFont = eaTypeface;
40705
42076
  }
40706
- const csTypeface = this.resolveThemeTypeface(xmlAttr(complexScript, "typeface"));
42077
+ const csTypeface = this.resolveThemeTypeface(csTypefaceToken);
40707
42078
  if (csTypeface) {
40708
42079
  style.complexScriptFont = csTypeface;
40709
42080
  }
@@ -40719,6 +42090,9 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40719
42090
  const capAttr = String(runProperties2["@_cap"] || "").trim().toLowerCase();
40720
42091
  if (capAttr === "all" || capAttr === "small") {
40721
42092
  style.textCaps = capAttr;
42093
+ } else if (capAttr === "none") {
42094
+ style.textCaps = "none";
42095
+ style.textCapsExplicitNone = true;
40722
42096
  }
40723
42097
  const symNode = xmlChild(runProperties2, "a:sym");
40724
42098
  if (symNode) {
@@ -40778,6 +42152,12 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40778
42152
  this.applyTextRunEffects(style, runEffectList);
40779
42153
  }
40780
42154
  this.applyTextRunEffectDag(style, runProperties2);
42155
+ if (includeDefaultAlignment) {
42156
+ const runExtLst = runProperties2["a:extLst"];
42157
+ if (runExtLst && typeof runExtLst === "object") {
42158
+ style.runPropertiesExtLstXml = runExtLst;
42159
+ }
42160
+ }
40781
42161
  return style;
40782
42162
  }
40783
42163
  /**
@@ -41449,12 +42829,63 @@ function writeCellTextFormatting(xmlCell, style, ensureArray16) {
41449
42829
  }
41450
42830
 
41451
42831
  // src/core/core/runtime/PptxHandlerRuntimeSaveTableStyles.ts
42832
+ function flattenCellTxBodyText(txBody, ensureArray16) {
42833
+ if (!txBody) {
42834
+ return "";
42835
+ }
42836
+ const paragraphs = ensureArray16(txBody["a:p"]);
42837
+ const lines = [];
42838
+ for (const paragraph of paragraphs) {
42839
+ const runs = ensureArray16(paragraph?.["a:r"]);
42840
+ const fields = ensureArray16(paragraph?.["a:fld"]);
42841
+ let lineText = "";
42842
+ for (const run of runs) {
42843
+ lineText += String(run?.["a:t"] ?? "");
42844
+ }
42845
+ for (const field of fields) {
42846
+ lineText += String(field?.["a:t"] ?? "");
42847
+ }
42848
+ lines.push(lineText);
42849
+ }
42850
+ return lines.join("\n");
42851
+ }
42852
+ function isRichCellTxBody(txBody, ensureArray16) {
42853
+ if (!txBody) {
42854
+ return false;
42855
+ }
42856
+ const paragraphs = ensureArray16(txBody["a:p"]);
42857
+ let totalRuns = 0;
42858
+ for (const paragraph of paragraphs) {
42859
+ const runs = ensureArray16(paragraph?.["a:r"]);
42860
+ totalRuns += runs.length;
42861
+ if (totalRuns > 1) {
42862
+ return true;
42863
+ }
42864
+ if (ensureArray16(paragraph?.["a:fld"]).length > 0) {
42865
+ return true;
42866
+ }
42867
+ for (const run of runs) {
42868
+ const rPr = run?.["a:rPr"];
42869
+ if (rPr?.["a:hlinkClick"] !== void 0) {
42870
+ return true;
42871
+ }
42872
+ }
42873
+ }
42874
+ return false;
42875
+ }
41452
42876
  var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime21 {
41453
42877
  /**
41454
42878
  * Write plain text into a table cell's txBody, preserving
41455
42879
  * existing run properties where possible.
41456
42880
  */
41457
42881
  writeTableCellText(xmlCell, text2) {
42882
+ const ensureArray16 = this.ensureArray.bind(this);
42883
+ const existingTxBody = xmlCell["a:txBody"];
42884
+ if (existingTxBody && ensureArray16(existingTxBody["a:p"]).length > 0) {
42885
+ if (flattenCellTxBodyText(existingTxBody, ensureArray16) === text2) {
42886
+ return;
42887
+ }
42888
+ }
41458
42889
  if (!xmlCell["a:txBody"]) {
41459
42890
  xmlCell["a:txBody"] = { "a:bodyPr": {}, "a:p": {} };
41460
42891
  }
@@ -41582,7 +43013,9 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
41582
43013
  }
41583
43014
  delete tcPr["a:tcMar"];
41584
43015
  writeDiagonalBorders(tcPr, style, _PptxHandlerRuntime.EMU_PER_PX);
41585
- writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
43016
+ if (!isRichCellTxBody(xmlCell["a:txBody"], this.ensureArray.bind(this))) {
43017
+ writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
43018
+ }
41586
43019
  const reordered = reorderObjectKeys(tcPr, TC_PR_BORDERS_ORDER);
41587
43020
  for (const key of Object.keys(tcPr)) {
41588
43021
  delete tcPr[key];
@@ -42826,7 +44259,7 @@ function findKey19(obj, name, getLocalName2) {
42826
44259
  function hex9(value) {
42827
44260
  return value.replace("#", "");
42828
44261
  }
42829
- var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
44262
+ var COLOR_LOCAL_NAMES2 = /* @__PURE__ */ new Set([
42830
44263
  "srgbClr",
42831
44264
  "schemeClr",
42832
44265
  "sysClr",
@@ -42835,7 +44268,7 @@ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
42835
44268
  "hslClr"
42836
44269
  ]);
42837
44270
  function applyColorToList(list, value, getLocalName2) {
42838
- const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES.has(getLocalName2(k)));
44271
+ const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES2.has(getLocalName2(k)));
42839
44272
  const srgb = { "@_val": hex9(value) };
42840
44273
  if (!colorKey) {
42841
44274
  list["a:srgbClr"] = srgb;
@@ -45327,6 +46760,33 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
45327
46760
  }
45328
46761
  };
45329
46762
 
46763
+ // src/core/core/runtime/save-line-fill.ts
46764
+ function writeLineFill(lineNode, shapeStyle, parseColor) {
46765
+ delete lineNode["a:noFill"];
46766
+ delete lineNode["a:solidFill"];
46767
+ delete lineNode["a:gradFill"];
46768
+ delete lineNode["a:pattFill"];
46769
+ if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
46770
+ lineNode["a:noFill"] = {};
46771
+ return;
46772
+ }
46773
+ if (shapeStyle.strokeFillMode === "gradient" && shapeStyle.strokeGradientXml) {
46774
+ lineNode["a:gradFill"] = shapeStyle.strokeGradientXml;
46775
+ return;
46776
+ }
46777
+ if (shapeStyle.strokeFillMode === "pattern" && shapeStyle.strokePatternXml) {
46778
+ lineNode["a:pattFill"] = shapeStyle.strokePatternXml;
46779
+ return;
46780
+ }
46781
+ const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? parseColor(shapeStyle.strokeColorXml) : void 0;
46782
+ lineNode["a:solidFill"] = serializeColorChoice(
46783
+ shapeStyle.strokeColorXml,
46784
+ resolvedStrokeOriginal,
46785
+ shapeStyle.strokeColor ?? "#000000",
46786
+ shapeStyle.strokeOpacity
46787
+ );
46788
+ }
46789
+
45330
46790
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeStyleWriter.ts
45331
46791
  var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime27 {
45332
46792
  /**
@@ -45397,26 +46857,14 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45397
46857
  );
45398
46858
  }
45399
46859
  }
45400
- if (shapeStyle.strokeColor !== void 0) {
46860
+ if (shapeStyle.strokeColor !== void 0 || shapeStyle.strokeFillMode === "gradient" || shapeStyle.strokeFillMode === "pattern") {
45401
46861
  if (!spPr["a:ln"]) {
45402
46862
  spPr["a:ln"] = {};
45403
46863
  }
45404
46864
  const lineNode = spPr["a:ln"];
45405
46865
  const w = Math.round((shapeStyle.strokeWidth || 1) * _PptxHandlerRuntime.EMU_PER_PX);
45406
46866
  lineNode["@_w"] = String(w);
45407
- if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
45408
- lineNode["a:noFill"] = {};
45409
- delete lineNode["a:solidFill"];
45410
- } else {
45411
- delete lineNode["a:noFill"];
45412
- const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? this.parseColor(shapeStyle.strokeColorXml) : void 0;
45413
- lineNode["a:solidFill"] = serializeColorChoice(
45414
- shapeStyle.strokeColorXml,
45415
- resolvedStrokeOriginal,
45416
- shapeStyle.strokeColor,
45417
- shapeStyle.strokeOpacity
45418
- );
45419
- }
46867
+ this.applyLineFill(lineNode, shapeStyle);
45420
46868
  }
45421
46869
  if (shapeStyle.strokeDash !== void 0) {
45422
46870
  if (!spPr["a:ln"]) {
@@ -45506,6 +46954,15 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45506
46954
  spPr["a:ln"]["a:effectLst"] = lineEffectListXml;
45507
46955
  }
45508
46956
  }
46957
+ /**
46958
+ * Emit the single fill child of an `<a:ln>` (CT_LineProperties allows at
46959
+ * most one of noFill/solidFill/gradFill/pattFill). Delegates to
46960
+ * {@link writeLineFill} so the logic stays unit-testable without the full
46961
+ * save runtime (issue #87).
46962
+ */
46963
+ applyLineFill(lineNode, shapeStyle) {
46964
+ writeLineFill(lineNode, shapeStyle, (colorNode) => this.parseColor(colorNode));
46965
+ }
45509
46966
  /**
45510
46967
  * Serialize the shape's `<p:style>` block (CT_ShapeStyle §20.1.2.2.36)
45511
46968
  * from the persisted ref indices/colour XML. Emits children in spec
@@ -45661,45 +47118,18 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45661
47118
  const s3d = shapeStyle.scene3d;
45662
47119
  const hasData = s3d.cameraPreset || s3d.lightRigType;
45663
47120
  if (hasData) {
45664
- const cameraObj = {};
45665
- if (s3d.cameraPreset) {
45666
- cameraObj["@_prst"] = s3d.cameraPreset;
45667
- }
45668
- if (s3d.cameraRotX !== void 0 || s3d.cameraRotY !== void 0 || s3d.cameraRotZ !== void 0) {
45669
- const rot = {};
45670
- if (s3d.cameraRotX !== void 0) {
45671
- rot["@_lat"] = String(s3d.cameraRotX);
45672
- }
45673
- if (s3d.cameraRotY !== void 0) {
45674
- rot["@_lon"] = String(s3d.cameraRotY);
45675
- }
45676
- if (s3d.cameraRotZ !== void 0) {
45677
- rot["@_rev"] = String(s3d.cameraRotZ);
45678
- }
45679
- cameraObj["a:rot"] = rot;
45680
- }
45681
- const lightRigObj = {};
45682
- if (s3d.lightRigType) {
45683
- lightRigObj["@_rig"] = s3d.lightRigType;
45684
- }
45685
- if (s3d.lightRigDirection) {
45686
- lightRigObj["@_dir"] = s3d.lightRigDirection;
45687
- }
45688
- const scene3dXml = {};
45689
- scene3dXml["a:camera"] = cameraObj;
45690
- if (Object.keys(lightRigObj).length > 0) {
45691
- scene3dXml["a:lightRig"] = lightRigObj;
45692
- }
45693
- if (s3d.hasBackdrop) {
45694
- const backdropObj = {};
45695
- if (s3d.backdropAnchorX !== void 0 || s3d.backdropAnchorY !== void 0 || s3d.backdropAnchorZ !== void 0) {
45696
- backdropObj["a:anchor"] = {
45697
- "@_x": String(s3d.backdropAnchorX ?? 0),
45698
- "@_y": String(s3d.backdropAnchorY ?? 0),
45699
- "@_z": String(s3d.backdropAnchorZ ?? 0)
45700
- };
45701
- }
45702
- scene3dXml["a:backdrop"] = backdropObj;
47121
+ const source = spPr["a:scene3d"] ?? {};
47122
+ const scene3dXml = { ...source };
47123
+ scene3dXml["a:camera"] = buildScene3dCamera(s3d, source);
47124
+ const lightRig = buildScene3dLightRig(s3d, source);
47125
+ if (lightRig) {
47126
+ scene3dXml["a:lightRig"] = lightRig;
47127
+ }
47128
+ const backdrop = buildScene3dBackdrop(s3d);
47129
+ if (backdrop) {
47130
+ scene3dXml["a:backdrop"] = backdrop;
47131
+ } else {
47132
+ delete scene3dXml["a:backdrop"];
45703
47133
  }
45704
47134
  spPr["a:scene3d"] = scene3dXml;
45705
47135
  } else {
@@ -45744,12 +47174,12 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45744
47174
  }
45745
47175
  if (sh3d.extrusionColor) {
45746
47176
  sp3dXml["a:extrusionClr"] = {
45747
- "a:srgbClr": { "@_val": sh3d.extrusionColor }
47177
+ "a:srgbClr": { "@_val": sh3d.extrusionColor.replace("#", "") }
45748
47178
  };
45749
47179
  }
45750
47180
  if (sh3d.contourColor) {
45751
47181
  sp3dXml["a:contourClr"] = {
45752
- "a:srgbClr": { "@_val": sh3d.contourColor }
47182
+ "a:srgbClr": { "@_val": sh3d.contourColor.replace("#", "") }
45753
47183
  };
45754
47184
  }
45755
47185
  spPr["a:sp3d"] = sp3dXml;
@@ -45761,6 +47191,77 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45761
47191
  }
45762
47192
  }
45763
47193
  };
47194
+ function buildSphereRot(lat, lon, rev) {
47195
+ if (lat === void 0 && lon === void 0 && rev === void 0) {
47196
+ return void 0;
47197
+ }
47198
+ const rot = {};
47199
+ if (lat !== void 0) {
47200
+ rot["@_lat"] = String(lat);
47201
+ }
47202
+ if (lon !== void 0) {
47203
+ rot["@_lon"] = String(lon);
47204
+ }
47205
+ if (rev !== void 0) {
47206
+ rot["@_rev"] = String(rev);
47207
+ }
47208
+ return rot;
47209
+ }
47210
+ function buildScene3dCamera(s3d, source) {
47211
+ const camera = { ...source["a:camera"] ?? {} };
47212
+ if (s3d.cameraPreset) {
47213
+ camera["@_prst"] = s3d.cameraPreset;
47214
+ }
47215
+ if (s3d.cameraFieldOfView !== void 0) {
47216
+ camera["@_fov"] = String(s3d.cameraFieldOfView);
47217
+ }
47218
+ if (s3d.cameraZoom !== void 0) {
47219
+ camera["@_zoom"] = String(s3d.cameraZoom);
47220
+ }
47221
+ const rot = buildSphereRot(s3d.cameraRotX, s3d.cameraRotY, s3d.cameraRotZ);
47222
+ if (rot) {
47223
+ camera["a:rot"] = rot;
47224
+ }
47225
+ return camera;
47226
+ }
47227
+ function buildScene3dLightRig(s3d, source) {
47228
+ const lightRig = { ...source["a:lightRig"] ?? {} };
47229
+ if (s3d.lightRigType) {
47230
+ lightRig["@_rig"] = s3d.lightRigType;
47231
+ }
47232
+ if (s3d.lightRigDirection) {
47233
+ lightRig["@_dir"] = s3d.lightRigDirection;
47234
+ }
47235
+ const rot = buildSphereRot(s3d.lightRigRotX, s3d.lightRigRotY, s3d.lightRigRotZ);
47236
+ if (rot) {
47237
+ lightRig["a:rot"] = rot;
47238
+ }
47239
+ return Object.keys(lightRig).length > 0 ? lightRig : void 0;
47240
+ }
47241
+ function buildScene3dBackdrop(s3d) {
47242
+ const hasNorm = s3d.backdropNormalX !== void 0 || s3d.backdropNormalY !== void 0 || s3d.backdropNormalZ !== void 0;
47243
+ const hasUp = s3d.backdropUpX !== void 0 || s3d.backdropUpY !== void 0 || s3d.backdropUpZ !== void 0;
47244
+ if (!s3d.hasBackdrop || !hasNorm || !hasUp) {
47245
+ return void 0;
47246
+ }
47247
+ return {
47248
+ "a:anchor": {
47249
+ "@_x": String(s3d.backdropAnchorX ?? 0),
47250
+ "@_y": String(s3d.backdropAnchorY ?? 0),
47251
+ "@_z": String(s3d.backdropAnchorZ ?? 0)
47252
+ },
47253
+ "a:norm": {
47254
+ "@_dx": String(s3d.backdropNormalX ?? 0),
47255
+ "@_dy": String(s3d.backdropNormalY ?? 0),
47256
+ "@_dz": String(s3d.backdropNormalZ ?? 0)
47257
+ },
47258
+ "a:up": {
47259
+ "@_dx": String(s3d.backdropUpX ?? 0),
47260
+ "@_dy": String(s3d.backdropUpY ?? 0),
47261
+ "@_dz": String(s3d.backdropUpZ ?? 0)
47262
+ }
47263
+ };
47264
+ }
45764
47265
 
45765
47266
  // src/core/core/runtime/PptxHandlerRuntimeSaveTextWriter.ts
45766
47267
  var PptxHandlerRuntime30 = class _PptxHandlerRuntime extends PptxHandlerRuntime29 {
@@ -47801,14 +49302,20 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
47801
49302
  relationshipType: constants.slideSyncRelationshipType,
47802
49303
  contentType: constants.slideSyncContentType
47803
49304
  });
47804
- this.slideBackgroundBuilder.applyBackground({
49305
+ await this.slideBackgroundBuilder.applyBackground({
47805
49306
  slideNode,
47806
49307
  slide,
47807
49308
  zip: this.zip,
47808
49309
  saveState: saveSession,
47809
49310
  relationshipRegistry: slideRelationshipRegistry,
47810
49311
  slideImageRelationshipType: constants.slideImageRelationshipType,
47811
- parseDataUrlToBytes: (dataUrl) => this.parseDataUrlToBytes(dataUrl)
49312
+ resolveImageToBytes: (url) => this.resolveMediaToBytes(url),
49313
+ reportUnsupportedBackground: (imageUrl) => this.compatibilityService.reportWarning({
49314
+ code: "SAVE_BACKGROUND_IMAGE_UNSUPPORTED",
49315
+ message: `Slide background image could not be embedded and was preserved as-is or omitted: ${imageUrl.slice(0, 120)}`,
49316
+ scope: "save",
49317
+ slideId: slide.id
49318
+ })
47812
49319
  });
47813
49320
  this.slideCommentPartWriter.writeComments({
47814
49321
  slide,
@@ -49313,7 +50820,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49313
50820
  } = saveConstants;
49314
50821
  this.compatibilityService.resetWarnings();
49315
50822
  const saveSession = new PptxSaveStateBuilder().withZip(this.zip).withCommentAuthorMap(this.commentAuthorMap).withCommentAuthorDetails(this.commentAuthorDetails).withCommentAuthorsRootXml(this.commentAuthorsRootXml).withEmuPerPx(_PptxHandlerRuntime.EMU_PER_PX).build();
49316
- await this.reconcilePresentationSlidesForSave({
50823
+ const slideReferenceRemap = await this.reconcilePresentationSlidesForSave({
49317
50824
  slides,
49318
50825
  saveSession,
49319
50826
  slideRelationshipType,
@@ -49408,7 +50915,8 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49408
50915
  rawSlideWidthEmu: this.rawSlideWidthEmu,
49409
50916
  rawSlideHeightEmu: this.rawSlideHeightEmu,
49410
50917
  rawSlideSizeType: this.rawSlideSizeType,
49411
- xmlLookupService: this.xmlLookupService
50918
+ xmlLookupService: this.xmlLookupService,
50919
+ slideReferenceRemap
49412
50920
  });
49413
50921
  this.deduplicateExtensionLists(this.presentationData);
49414
50922
  if (effectiveConformance === "transitional") {
@@ -49425,7 +50933,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49425
50933
  printSlidesPerPage: options.handoutMaster.slidesPerPage
49426
50934
  } : options?.presentationProperties;
49427
50935
  await this.applyPresentationPropertiesPart(presentationProperties);
49428
- await this.applyViewPropertiesPart(options?.viewProperties);
50936
+ await this.applyViewPropertiesPart(options?.viewProperties ?? this.loadedViewProperties);
49429
50937
  await this.applyTableStylesPart(options?.tableStyles);
49430
50938
  await this.documentPropertiesUpdater.updateOnSave(slides, {
49431
50939
  coreProperties: options?.coreProperties,
@@ -49713,26 +51221,16 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49713
51221
  return true;
49714
51222
  }
49715
51223
  const typesMatch = source.type === target.type || source.type === "ctrtitle" && target.type === "title" || source.type === "subtitle" && target.type === "body";
49716
- if (source.idx !== void 0 && target.idx !== void 0) {
49717
- if (source.idx !== target.idx) {
49718
- return false;
49719
- }
49720
- if (source.type && target.type && !typesMatch) {
49721
- return false;
49722
- }
49723
- return true;
49724
- }
49725
- if (source.idx !== void 0 && target.idx === void 0) {
49726
- const singletonTypes = /* @__PURE__ */ new Set(["title", "ctrtitle", "subtitle", "dt", "ftr", "sldnum"]);
49727
- if (source.type && singletonTypes.has(source.type)) {
49728
- return typesMatch;
49729
- }
51224
+ const sourceIdx = source.idx ?? "0";
51225
+ const targetIdx = target.idx ?? "0";
51226
+ if (sourceIdx !== targetIdx) {
49730
51227
  return false;
49731
51228
  }
49732
51229
  if (source.type && target.type && !typesMatch) {
49733
51230
  return false;
49734
51231
  }
49735
- if (source.type && !target.type) {
51232
+ const bothHaveExplicitIdx = source.idx !== void 0 && target.idx !== void 0;
51233
+ if (!bothHaveExplicitIdx && source.type && !target.type) {
49736
51234
  return false;
49737
51235
  }
49738
51236
  return true;
@@ -51178,6 +52676,19 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51178
52676
  });
51179
52677
  return hasAny ? locks : void 0;
51180
52678
  }
52679
+ /**
52680
+ * Parse the `@txBox` attribute from a `p:cNvSpPr` node. Returns `true` /
52681
+ * `false` when the attribute is present, or `undefined` when absent so
52682
+ * callers can distinguish "not a text box" from "unspecified".
52683
+ */
52684
+ parseTxBoxFlag(cNvSpPr) {
52685
+ const raw = cNvSpPr?.["@_txBox"];
52686
+ if (raw === void 0) {
52687
+ return void 0;
52688
+ }
52689
+ const val = String(raw).trim().toLowerCase();
52690
+ return val === "1" || val === "true";
52691
+ }
51181
52692
  /**
51182
52693
  * Extract body-level text properties from `a:bodyPr` and apply them to the
51183
52694
  * provided {@link TextStyle}. Returns linked-textbox info when present.
@@ -51360,6 +52871,62 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51360
52871
 
51361
52872
  // src/core/core/runtime/PptxHandlerRuntimeShapeTextParsing.ts
51362
52873
  var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime61 {
52874
+ /**
52875
+ * Extract a paragraph's OWN `a:pPr` geometry (align, spacing, margins,
52876
+ * indent, tabs, rtl) as a partial {@link TextStyle} so per-paragraph
52877
+ * formatting round-trips rather than collapsing to one shape-level pPr
52878
+ * (#69). Inherited layout/master values are not re-stamped.
52879
+ */
52880
+ extractParagraphOwnProperties(p, basisFontSize) {
52881
+ const pPr = p["a:pPr"];
52882
+ if (!pPr) {
52883
+ return void 0;
52884
+ }
52885
+ const pp = { ...parseParagraphMargins(pPr) };
52886
+ const align = pPr["@_algn"] !== void 0 ? parseAlignmentAttr(String(pPr["@_algn"])) : void 0;
52887
+ if (align) {
52888
+ pp.align = align;
52889
+ }
52890
+ const rtl = parseParagraphRtl(pPr);
52891
+ if (rtl !== void 0) {
52892
+ pp.rtl = rtl;
52893
+ }
52894
+ const spcBef = this.parseParagraphSpacingPx(
52895
+ pPr["a:spcBef"],
52896
+ basisFontSize
52897
+ );
52898
+ if (spcBef !== void 0) {
52899
+ pp.paragraphSpacingBefore = spcBef;
52900
+ }
52901
+ const spcAft = this.parseParagraphSpacingPx(
52902
+ pPr["a:spcAft"],
52903
+ basisFontSize
52904
+ );
52905
+ if (spcAft !== void 0) {
52906
+ pp.paragraphSpacingAfter = spcAft;
52907
+ }
52908
+ const lnSpcNode = pPr["a:lnSpc"];
52909
+ const lineSpacing = this.parseLineSpacingMultiplier(lnSpcNode);
52910
+ const exactPt = lineSpacing === void 0 ? this.parseLineSpacingExactPt(lnSpcNode) : void 0;
52911
+ if (lineSpacing !== void 0) {
52912
+ pp.lineSpacing = lineSpacing;
52913
+ } else if (exactPt !== void 0) {
52914
+ pp.lineSpacingExactPt = exactPt;
52915
+ }
52916
+ const tabStops = parseTabStops(pPr);
52917
+ if (tabStops && tabStops.length > 0) {
52918
+ pp.tabStops = tabStops;
52919
+ }
52920
+ const defRPr = pPr["a:defRPr"];
52921
+ if (defRPr && typeof defRPr === "object") {
52922
+ pp.paragraphDefaultRunPropertiesXml = defRPr;
52923
+ }
52924
+ const pPrExtLst = pPr["a:extLst"];
52925
+ if (pPrExtLst && typeof pPrExtLst === "object") {
52926
+ pp.paragraphPropertiesExtLstXml = pPrExtLst;
52927
+ }
52928
+ return Object.keys(pp).length > 0 ? pp : void 0;
52929
+ }
51363
52930
  /**
51364
52931
  * Resolve paragraph-level styles (alignment, spacing, margins, tabs,
51365
52932
  * level styles) for a single paragraph. Modifies `textStyle` in place
@@ -51608,6 +53175,12 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51608
53175
  ...mergedDefaultRunStyle,
51609
53176
  ...this.extractTextRunStyle(runProps, paraAlign, ctx.slideRelationshipMap)
51610
53177
  };
53178
+ if (!runStyle2.scriptFallbackFont) {
53179
+ const fallback = this.resolveScriptFallbackFont(runText);
53180
+ if (fallback) {
53181
+ runStyle2.scriptFallbackFont = fallback;
53182
+ }
53183
+ }
51611
53184
  parts.push(runText);
51612
53185
  segments.push({ text: runText, style: runStyle2 });
51613
53186
  maybeSeed(runStyle2);
@@ -51649,14 +53222,25 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51649
53222
  )
51650
53223
  };
51651
53224
  const fldType = String(field["@_type"] || "").trim() || void 0;
51652
- const fldGuid = String(field["@_uuid"] || field["@_id"] || "").trim() || void 0;
53225
+ const uuidAttr = String(field["@_uuid"] || "").trim();
53226
+ const idAttr = String(field["@_id"] || "").trim();
53227
+ const fldGuid = uuidAttr || idAttr || void 0;
53228
+ const fldGuidAttr = uuidAttr ? "uuid" : idAttr ? "id" : void 0;
51653
53229
  parts.push(fieldText);
51654
- segments.push({
53230
+ const fieldSegment = {
51655
53231
  text: fieldText,
51656
53232
  style: fieldRunStyle,
51657
53233
  fieldType: fldType,
51658
53234
  fieldGuid: fldGuid
51659
- });
53235
+ };
53236
+ if (fldGuidAttr) {
53237
+ fieldSegment.fieldGuidAttr = fldGuidAttr;
53238
+ }
53239
+ const fieldPPr = field["a:pPr"];
53240
+ if (fieldPPr && typeof fieldPPr === "object") {
53241
+ fieldSegment.fieldParagraphPropertiesXml = fieldPPr;
53242
+ }
53243
+ segments.push(fieldSegment);
51660
53244
  maybeSeed(fieldRunStyle);
51661
53245
  };
51662
53246
  const processMathElement = (mathEl) => {
@@ -51783,6 +53367,11 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51783
53367
  ...endParaRPrRaw
51784
53368
  };
51785
53369
  }
53370
+ const basisFontSize = typeof mergedDefaultRunStyle.fontSize === "number" ? mergedDefaultRunStyle.fontSize : void 0;
53371
+ const paragraphOwnProps = this.extractParagraphOwnProperties(p, basisFontSize);
53372
+ if (paragraphOwnProps) {
53373
+ segments[firstSegmentIndex].paragraphProperties = paragraphOwnProps;
53374
+ }
51786
53375
  }
51787
53376
  return { parts, segments, seedStyle };
51788
53377
  }
@@ -52091,7 +53680,11 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52091
53680
  const inheritedCNvSpPr = xmlPath(inheritedPlaceholder?.shape, "p:nvSpPr", "p:cNvSpPr") ?? xmlPath(inheritedPlaceholder?.picture, "p:nvPicPr", "p:cNvPicPr");
52092
53681
  const inheritedLockNode = inheritedCNvSpPr?.["a:spLocks"] ?? inheritedCNvSpPr?.["a:picLocks"];
52093
53682
  const inheritedLocks = this.parseShapeLocks(inheritedLockNode);
52094
- const locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
53683
+ let locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
53684
+ const txBox = this.parseTxBoxFlag(cNvSpPr);
53685
+ if (txBox !== void 0) {
53686
+ locks = { ...locks ?? {}, txBox };
53687
+ }
52095
53688
  const promptText = !hasText && phDefaults?.promptText ? phDefaults.promptText : void 0;
52096
53689
  const opaqueExtLstXml = this.extractOpaqueSpPrExtLst(effectiveSpPr);
52097
53690
  const commonProps = {
@@ -52190,7 +53783,7 @@ var PptxHandlerRuntime65 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52190
53783
  const skewY = xfrm["@_skewY"] ? parseEmuInt(xfrm["@_skewY"]) / 6e4 : void 0;
52191
53784
  const { flipHorizontal, flipVertical } = this.readFlipState(xfrm);
52192
53785
  const nvPr = pic?.["p:nvPicPr"]?.["p:nvPr"];
52193
- const mediaReference = parseDrawingMediaReference(nvPr);
53786
+ const mediaReference = parseDrawingMediaReference(nvPr, this.externalRelsMap.get(slidePath));
52194
53787
  if (mediaReference) {
52195
53788
  this.compatibilityService.inspectMediaReferenceCompatibility(
52196
53789
  mediaReference.kind,
@@ -52958,6 +54551,9 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52958
54551
  const grpSpPr = group["p:grpSpPr"];
52959
54552
  const xfrm = grpSpPr?.["a:xfrm"];
52960
54553
  let parentX = 0, parentY = 0, parentW = 0, parentH = 0;
54554
+ let groupRotation;
54555
+ let flipHorizontal = false;
54556
+ let flipVertical = false;
52961
54557
  if (xfrm) {
52962
54558
  const off = xfrm["a:off"];
52963
54559
  if (off) {
@@ -52969,6 +54565,12 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52969
54565
  parentW = Math.round(parseEmuInt2(ext["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
52970
54566
  parentH = Math.round(parseEmuInt2(ext["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
52971
54567
  }
54568
+ if (xfrm["@_rot"] !== void 0 && xfrm["@_rot"] !== null) {
54569
+ const rot = parseInt(String(xfrm["@_rot"]), 10) / 6e4;
54570
+ groupRotation = Number.isFinite(rot) && rot !== 0 ? rot : void 0;
54571
+ }
54572
+ flipHorizontal = this.parseBooleanAttr(xfrm["@_flipH"]);
54573
+ flipVertical = this.parseBooleanAttr(xfrm["@_flipV"]);
52972
54574
  }
52973
54575
  const grpFillStyle = grpSpPr ? this.extractShapeStyle(grpSpPr) : void 0;
52974
54576
  const hasGroupFill = grpFillStyle && grpFillStyle.fillMode && grpFillStyle.fillMode !== "none";
@@ -53014,6 +54616,9 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
53014
54616
  y: parentY,
53015
54617
  width: parentW || Math.max(...children9.map((c) => c.x + c.width)),
53016
54618
  height: parentH || Math.max(...children9.map((c) => c.y + c.height)),
54619
+ rotation: groupRotation,
54620
+ flipHorizontal: flipHorizontal || void 0,
54621
+ flipVertical: flipVertical || void 0,
53017
54622
  children: children9,
53018
54623
  rawXml: group,
53019
54624
  actionClick: grpActionClick,
@@ -54030,9 +55635,9 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
54030
55635
  }
54031
55636
  const buClr = levelProps["a:buClr"];
54032
55637
  if (buClr) {
54033
- const srgb = buClr["a:srgbClr"];
54034
- if (srgb?.["@_val"]) {
54035
- style.bulletColor = String(srgb["@_val"]);
55638
+ const bulletColor = this.parseColor(buClr);
55639
+ if (bulletColor) {
55640
+ style.bulletColor = bulletColor;
54036
55641
  }
54037
55642
  }
54038
55643
  const buSzPts = levelProps["a:buSzPts"];
@@ -55632,16 +57237,20 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
55632
57237
  }
55633
57238
  let fontScheme;
55634
57239
  if (hasFonts) {
57240
+ const majorByScript = this.aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
57241
+ const minorByScript = this.aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
55635
57242
  fontScheme = {
55636
57243
  majorFont: {
55637
57244
  latin: this.themeFontMap["mj-lt"],
55638
57245
  eastAsia: this.themeFontMap["mj-ea"],
55639
- complexScript: this.themeFontMap["mj-cs"]
57246
+ complexScript: this.themeFontMap["mj-cs"],
57247
+ ...Object.keys(majorByScript).length > 0 ? { byScript: majorByScript } : {}
55640
57248
  },
55641
57249
  minorFont: {
55642
57250
  latin: this.themeFontMap["mn-lt"],
55643
57251
  eastAsia: this.themeFontMap["mn-ea"],
55644
- complexScript: this.themeFontMap["mn-cs"]
57252
+ complexScript: this.themeFontMap["mn-cs"],
57253
+ ...Object.keys(minorByScript).length > 0 ? { byScript: minorByScript } : {}
55645
57254
  }
55646
57255
  };
55647
57256
  }
@@ -55849,6 +57458,23 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
55849
57458
  *
55850
57459
  * Phase 4 Stream A / M4.
55851
57460
  */
57461
+ /**
57462
+ * Flatten a per-theme-path script-override map (`themePath -> {script ->
57463
+ * typeface}`) into a single `{script -> typeface}` lookup for
57464
+ * {@link buildThemeObject}. Earlier entries win on collision, which matches
57465
+ * the primary-theme-first parse order. Phase 4 Stream A / M4 (#83).
57466
+ */
57467
+ aggregateFontScriptOverrides(perPathMap) {
57468
+ const aggregate = {};
57469
+ for (const overrides of perPathMap.values()) {
57470
+ for (const [script, typeface] of Object.entries(overrides)) {
57471
+ if (!(script in aggregate)) {
57472
+ aggregate[script] = typeface;
57473
+ }
57474
+ }
57475
+ }
57476
+ return aggregate;
57477
+ }
55852
57478
  collectFontScriptOverrides(fontNode) {
55853
57479
  const overrides = {};
55854
57480
  if (!fontNode) {
@@ -56484,33 +58110,16 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
56484
58110
  const metadata = parseSmartArtDefinitionMetadata(colorsDef, localName21);
56485
58111
  const labels = parseSmartArtColorStyleLabels(colorsDef, localName21);
56486
58112
  const name = metadata.titles?.[0]?.value || String(colorsDef["@_title"] || colorsDef["@_uniqueId"] || "").trim() || void 0;
56487
- const fillColors = [];
56488
- const lineColors = [];
56489
58113
  const styleLbls = this.xmlLookupService.getChildrenArrayByLocalName(colorsDef, "styleLbl");
56490
- for (const lbl of styleLbls) {
56491
- const fillClrLst = this.xmlLookupService.getChildByLocalName(lbl, "fillClrLst");
56492
- const linClrLst = this.xmlLookupService.getChildByLocalName(lbl, "linClrLst");
56493
- if (fillClrLst) {
56494
- const color2 = this.parseColor(fillClrLst) ?? this.resolveSmartArtSchemeColor(
56495
- this.xmlLookupService.getChildByLocalName(fillClrLst, "schemeClr")
56496
- );
56497
- if (color2) {
56498
- fillColors.push(color2);
56499
- }
56500
- }
56501
- if (linClrLst) {
56502
- const color2 = this.parseColor(linClrLst) ?? this.resolveSmartArtSchemeColor(
56503
- this.xmlLookupService.getChildByLocalName(linClrLst, "schemeClr")
56504
- );
56505
- if (color2) {
56506
- lineColors.push(color2);
56507
- }
56508
- }
56509
- }
56510
- if (fillColors.length === 0 && lineColors.length === 0) {
58114
+ const colorLists = buildSmartArtColorLists(styleLbls, {
58115
+ getChild: (node, childName) => this.xmlLookupService.getChildByLocalName(node, childName),
58116
+ parseColorChoice: (colorChoice) => this.parseColor(colorChoice),
58117
+ resolveScheme: (colorNode) => this.resolveSmartArtSchemeColor(colorNode)
58118
+ });
58119
+ if (colorLists.fillColors.length === 0 && colorLists.lineColors.length === 0) {
56511
58120
  return void 0;
56512
58121
  }
56513
- return { ...metadata, name, fillColors, lineColors, labels };
58122
+ return { ...metadata, name, ...colorLists, labels };
56514
58123
  } catch {
56515
58124
  return void 0;
56516
58125
  }
@@ -56534,6 +58143,89 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
56534
58143
  }
56535
58144
  };
56536
58145
 
58146
+ // src/core/core/runtime/smartart-drawing-shape-style.ts
58147
+ function extractDrawingShapeFill(spPr, deps) {
58148
+ const result = {};
58149
+ const solidFill2 = deps.getChild(spPr, "solidFill");
58150
+ if (solidFill2) {
58151
+ result.fillColor = deps.parseColor(solidFill2) ?? void 0;
58152
+ }
58153
+ const gradFill = !solidFill2 ? deps.getChild(spPr, "gradFill") : void 0;
58154
+ if (gradFill) {
58155
+ const stops = deps.extractGradientStops(gradFill).map((stop) => ({
58156
+ color: stop.color,
58157
+ position: stop.position,
58158
+ ...stop.opacity !== void 0 ? { opacity: stop.opacity } : {}
58159
+ }));
58160
+ if (stops.length > 0) {
58161
+ result.fillGradientStops = stops;
58162
+ result.fillGradientType = deps.extractGradientType(gradFill);
58163
+ result.fillGradientAngle = deps.extractGradientAngle(gradFill);
58164
+ result.fillColor ??= stops[Math.floor(stops.length / 2)]?.color;
58165
+ }
58166
+ }
58167
+ const pattFill = !solidFill2 && !gradFill ? deps.getChild(spPr, "pattFill") : void 0;
58168
+ if (pattFill) {
58169
+ const preset = String(pattFill["@_prst"] || "").trim();
58170
+ if (preset) {
58171
+ result.fillPatternPreset = preset;
58172
+ }
58173
+ const fg = deps.parseColor(deps.getChild(pattFill, "fgClr"));
58174
+ const bg = deps.parseColor(deps.getChild(pattFill, "bgClr"));
58175
+ if (fg) {
58176
+ result.fillPatternForegroundColor = fg;
58177
+ }
58178
+ if (bg) {
58179
+ result.fillPatternBackgroundColor = bg;
58180
+ }
58181
+ result.fillColor ??= fg ?? bg;
58182
+ }
58183
+ const blipFill = !solidFill2 && !gradFill && !pattFill ? deps.getChild(spPr, "blipFill") : void 0;
58184
+ if (blipFill) {
58185
+ const blip = deps.getChild(blipFill, "blip");
58186
+ const embed = String(
58187
+ blip?.["@_r:embed"] || blip?.["@_embed"] || blip?.["@_r:link"] || ""
58188
+ ).trim();
58189
+ if (embed) {
58190
+ result.fillBlipEmbedId = embed;
58191
+ }
58192
+ }
58193
+ const shadowColor = deps.extractShadowColor(spPr);
58194
+ if (shadowColor) {
58195
+ result.hasShadow = true;
58196
+ result.shadowColor = shadowColor;
58197
+ }
58198
+ return result;
58199
+ }
58200
+ function extractDrawingShapeTextStyle(txBody, deps) {
58201
+ let fontSize;
58202
+ let fontColor;
58203
+ if (!txBody) {
58204
+ return { fontSize, fontColor };
58205
+ }
58206
+ const paragraphs = deps.getChildren(txBody, "p");
58207
+ for (const p of paragraphs) {
58208
+ const runs = deps.getChildren(p, "r");
58209
+ for (const r of runs) {
58210
+ const rPr = deps.getChild(r, "rPr");
58211
+ if (rPr && !fontSize) {
58212
+ const szRaw = parseInt(String(rPr["@_sz"] || ""), 10);
58213
+ if (Number.isFinite(szRaw) && szRaw > 0) {
58214
+ fontSize = szRaw / 100;
58215
+ }
58216
+ fontColor = deps.parseColor(deps.getChild(rPr, "solidFill")) ?? void 0;
58217
+ }
58218
+ if (fontSize) {
58219
+ break;
58220
+ }
58221
+ }
58222
+ if (fontSize) {
58223
+ break;
58224
+ }
58225
+ }
58226
+ return { fontSize, fontColor };
58227
+ }
58228
+
56537
58229
  // src/core/core/runtime/smartart-text-style-resolution.ts
56538
58230
  function resolveSmartArtTextStyles(paragraphs, resolve2) {
56539
58231
  for (const paragraph of paragraphs ?? []) {
@@ -56709,8 +58401,7 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56709
58401
  };
56710
58402
  }
56711
58403
  }
56712
- const solidFill2 = this.xmlLookupService.getChildByLocalName(spPr, "solidFill");
56713
- const fillColor = this.parseColor(solidFill2);
58404
+ const fill = extractDrawingShapeFill(spPr, this.drawingShapeStyleDeps());
56714
58405
  const lnNode = this.xmlLookupService.getChildByLocalName(spPr, "ln");
56715
58406
  const lnFill = lnNode ? this.xmlLookupService.getChildByLocalName(lnNode, "solidFill") : void 0;
56716
58407
  const strokeColor = this.parseColor(lnFill);
@@ -56722,7 +58413,10 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56722
58413
  this.collectLocalTextValues(txBody, "t", textValues2);
56723
58414
  }
56724
58415
  const text2 = textValues2.join("").trim() || void 0;
56725
- const { fontSize, fontColor } = this.extractDrawingShapeTextStyle(txBody);
58416
+ const { fontSize, fontColor } = extractDrawingShapeTextStyle(
58417
+ txBody,
58418
+ this.drawingShapeStyleDeps()
58419
+ );
56726
58420
  const paragraphs = txBody ? resolveSmartArtTextStyles(
56727
58421
  parseSmartArtTextParagraphs({ "dgm:t": txBody }),
56728
58422
  (rPr) => this.extractTextRunStyle(rPr, void 0, void 0, false)
@@ -56748,7 +58442,8 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56748
58442
  rotation,
56749
58443
  skewX,
56750
58444
  skewY,
56751
- fillColor: fillColor ?? void 0,
58445
+ ...fill,
58446
+ fillColor: fill.fillColor ?? void 0,
56752
58447
  strokeColor: strokeColor ?? void 0,
56753
58448
  strokeWidth,
56754
58449
  text: structuredText,
@@ -56758,36 +58453,126 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56758
58453
  ...customGeometry
56759
58454
  };
56760
58455
  }
56761
- extractDrawingShapeTextStyle(txBody) {
56762
- let fontSize;
56763
- let fontColor;
56764
- if (!txBody) {
56765
- return { fontSize, fontColor };
56766
- }
56767
- const paragraphs = this.xmlLookupService.getChildrenArrayByLocalName(txBody, "p");
56768
- for (const p of paragraphs) {
56769
- const runs = this.xmlLookupService.getChildrenArrayByLocalName(p, "r");
56770
- for (const r of runs) {
56771
- const rPr = this.xmlLookupService.getChildByLocalName(r, "rPr");
56772
- if (rPr && !fontSize) {
56773
- const szRaw = parseInt(String(rPr["@_sz"] || ""), 10);
56774
- if (Number.isFinite(szRaw) && szRaw > 0) {
56775
- fontSize = szRaw / 100;
56776
- }
56777
- const rprFill = this.xmlLookupService.getChildByLocalName(rPr, "solidFill");
56778
- fontColor = this.parseColor(rprFill) ?? void 0;
56779
- }
56780
- if (fontSize) {
56781
- break;
56782
- }
56783
- }
56784
- if (fontSize) {
56785
- break;
58456
+ /**
58457
+ * Build the injected accessor bundle used by the pure drawing-shape style
58458
+ * helpers, binding the shared XML-lookup / colour / gradient / shadow codec
58459
+ * methods so no new colour logic is duplicated here.
58460
+ */
58461
+ drawingShapeStyleDeps() {
58462
+ return {
58463
+ getChild: (node, local) => this.xmlLookupService.getChildByLocalName(node, local),
58464
+ getChildren: (node, local) => this.xmlLookupService.getChildrenArrayByLocalName(node, local),
58465
+ parseColor: (node) => this.parseColor(node),
58466
+ extractGradientStops: (gradFill) => this.extractGradientStops(gradFill),
58467
+ extractGradientType: (gradFill) => this.extractGradientType(gradFill),
58468
+ extractGradientAngle: (gradFill) => this.extractGradientAngle(gradFill),
58469
+ extractShadowColor: (spPr) => this.extractShadowStyle(spPr).shadowColor
58470
+ };
58471
+ }
58472
+ };
58473
+
58474
+ // src/core/core/runtime/smartart-drawing-blip.ts
58475
+ function collectDrawingShapeNodes(root, getChildren) {
58476
+ const out = [];
58477
+ const walk = (container) => {
58478
+ if (!container) {
58479
+ return;
58480
+ }
58481
+ for (const sp of getChildren(container, "sp")) {
58482
+ out.push({ node: sp, isPic: false });
58483
+ }
58484
+ for (const pic of getChildren(container, "pic")) {
58485
+ out.push({ node: pic, isPic: true });
58486
+ }
58487
+ for (const grp of getChildren(container, "grpSp")) {
58488
+ walk(grp);
58489
+ }
58490
+ };
58491
+ walk(root);
58492
+ return out;
58493
+ }
58494
+ function picBlipEmbedId(pic, getChild) {
58495
+ const blip = getChild(getChild(pic, "blipFill"), "blip");
58496
+ if (!blip) {
58497
+ return void 0;
58498
+ }
58499
+ const embed = String(blip["@_r:embed"] || blip["@_embed"] || blip["@_r:link"] || "").trim();
58500
+ return embed.length > 0 ? embed : void 0;
58501
+ }
58502
+ function parseDrawingRelTargets(relsXml, parse, ensureArray16) {
58503
+ const map = /* @__PURE__ */ new Map();
58504
+ try {
58505
+ const relsRoot = parse(relsXml)["Relationships"];
58506
+ if (!relsRoot) {
58507
+ return map;
58508
+ }
58509
+ for (const rel of ensureArray16(relsRoot["Relationship"])) {
58510
+ const id = String(rel?.["@_Id"] || "").trim();
58511
+ const target = String(rel?.["@_Target"] || "").trim();
58512
+ if (id.length > 0 && target.length > 0) {
58513
+ map.set(id, target);
56786
58514
  }
56787
58515
  }
56788
- return { fontSize, fontColor };
58516
+ } catch {
56789
58517
  }
56790
- };
58518
+ return map;
58519
+ }
58520
+ async function resolveDrawingBlipFills(shapes, drawingPath, deps) {
58521
+ const pending = shapes.filter((shape) => shape.fillBlipEmbedId && !shape.fillImageUrl);
58522
+ if (pending.length === 0) {
58523
+ return;
58524
+ }
58525
+ const dir = drawingPath.replace(/\/[^/]+$/u, "");
58526
+ const file = drawingPath.split("/").pop() ?? "";
58527
+ const relsXml = await deps.readText(`${dir}/_rels/${file}.rels`);
58528
+ if (!relsXml) {
58529
+ return;
58530
+ }
58531
+ const targets = parseDrawingRelTargets(relsXml, deps.parse, deps.ensureArray);
58532
+ for (const shape of pending) {
58533
+ const target = targets.get(shape.fillBlipEmbedId ?? "");
58534
+ if (!target) {
58535
+ continue;
58536
+ }
58537
+ const source = /^(?:https?:|data:)/u.test(target) ? target : deps.resolveImagePath(drawingPath, target);
58538
+ const resolved = await deps.getImageData(source);
58539
+ if (resolved) {
58540
+ shape.fillImageUrl = resolved;
58541
+ }
58542
+ }
58543
+ }
58544
+ async function parseDrawingShapesFromPart(drawingPath, deps) {
58545
+ const xmlString = await deps.readText(drawingPath);
58546
+ if (!xmlString) {
58547
+ return [];
58548
+ }
58549
+ try {
58550
+ const xml = deps.parse(xmlString);
58551
+ const drawing = deps.getChild(xml, "drawing");
58552
+ const spTree = deps.getChild(drawing || xml, "spTree");
58553
+ if (!spTree) {
58554
+ return [];
58555
+ }
58556
+ const shapes = [];
58557
+ collectDrawingShapeNodes(spTree, deps.getChildren).forEach(({ node, isPic }, index) => {
58558
+ const shape = deps.parseDrawingShape(node, index, deps.emuPerPx);
58559
+ if (!shape) {
58560
+ return;
58561
+ }
58562
+ if (isPic && !shape.fillBlipEmbedId) {
58563
+ const embed = picBlipEmbedId(node, deps.getChild);
58564
+ if (embed) {
58565
+ shape.fillBlipEmbedId = embed;
58566
+ }
58567
+ }
58568
+ shapes.push(shape);
58569
+ });
58570
+ await resolveDrawingBlipFills(shapes, drawingPath, deps);
58571
+ return shapes;
58572
+ } catch {
58573
+ return [];
58574
+ }
58575
+ }
56791
58576
 
56792
58577
  // src/core/core/runtime/smartart-layout-category.ts
56793
58578
  var CATEGORY_FAMILY = {
@@ -56924,6 +58709,7 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56924
58709
  layoutDefinition,
56925
58710
  nodes,
56926
58711
  connections: parsedConnections.length > 0 ? parsedConnections : void 0,
58712
+ presLayoutVars: parseSmartArtPresLayoutVars(dataModel),
56927
58713
  drawingShapes: drawingShapes.length > 0 ? drawingShapes : void 0,
56928
58714
  chrome,
56929
58715
  colorTransform,
@@ -57002,30 +58788,28 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
57002
58788
  }
57003
58789
  }
57004
58790
  /**
57005
- * Parse SmartArt drawing shapes given an absolute part path.
58791
+ * Parse cached SmartArt drawing shapes from an absolute part path.
57006
58792
  *
57007
- * Wraps `parseSmartArtDrawingShapes` (which expects a slide-relative
57008
- * relationship id) with a path-based lookup so the resolution layer
57009
- * can pull the part from anywhere in the package.
58793
+ * Enumerates `dsp:sp` / bare `dsp:pic` (incl. nested `dsp:grpSp`) and
58794
+ * resolves picture (blip) fills to data URLs via the drawing part's own
58795
+ * relationships. Delegates to a pure helper with an injected dep bundle.
57010
58796
  */
57011
58797
  async parseSmartArtDrawingShapesFromPath(drawingPath) {
57012
- const xmlString = await this.zip.file(drawingPath)?.async("string");
57013
- if (!xmlString) {
57014
- return [];
57015
- }
57016
- try {
57017
- const xml = this.parser.parse(xmlString);
57018
- const drawing = this.xmlLookupService.getChildByLocalName(xml, "drawing");
57019
- const spTree = this.xmlLookupService.getChildByLocalName(drawing || xml, "spTree");
57020
- if (!spTree) {
57021
- return [];
57022
- }
57023
- const shapes = this.xmlLookupService.getChildrenArrayByLocalName(spTree, "sp");
57024
- const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
57025
- return shapes.map((sp, index) => this.parseDrawingShape(sp, index, emuPerPx)).filter((entry) => entry !== null);
57026
- } catch {
57027
- return [];
57028
- }
58798
+ return parseDrawingShapesFromPart(drawingPath, this.drawingBlipDeps());
58799
+ }
58800
+ /** Bind runtime zip / parser / lookup / image helpers for the drawing parser. */
58801
+ drawingBlipDeps() {
58802
+ return {
58803
+ readText: (path2) => this.zip.file(path2)?.async("string") ?? Promise.resolve(void 0),
58804
+ parse: (xml) => this.parser.parse(xml),
58805
+ getChild: (node, local) => this.xmlLookupService.getChildByLocalName(node, local),
58806
+ getChildren: (node, local) => this.xmlLookupService.getChildrenArrayByLocalName(node, local),
58807
+ parseDrawingShape: (sp, index, emuPerPx) => this.parseDrawingShape(sp, index, emuPerPx),
58808
+ emuPerPx: _PptxHandlerRuntime.EMU_PER_PX,
58809
+ ensureArray: (value) => this.ensureArray(value),
58810
+ resolveImagePath: (base, target) => this.resolveImagePath(base, target),
58811
+ getImageData: (path2) => this.getImageData(path2)
58812
+ };
57029
58813
  }
57030
58814
  };
57031
58815
 
@@ -57723,6 +59507,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57723
59507
  grouping = "clustered";
57724
59508
  }
57725
59509
  }
59510
+ const varyColors = this.parseChartBoolVal(seriesContainer, "varyColors");
59511
+ const firstSliceAngle = this.parseChartNumberVal(seriesContainer, "firstSliceAng");
59512
+ const doughnutHoleSize = this.parseChartNumberVal(seriesContainer, "holeSize");
59513
+ const barGapWidth = this.parseChartNumberVal(seriesContainer, "gapWidth");
59514
+ const barOverlap = this.parseChartNumberVal(seriesContainer, "overlap");
57726
59515
  const chartPartPath = chartPart.partPath;
57727
59516
  const dataTable = parseDataTable(plotArea, this.xmlLookupService);
57728
59517
  const dropLines = parseLineStyle(
@@ -57799,6 +59588,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57799
59588
  title: titleTextValues[0],
57800
59589
  style: chartStyle,
57801
59590
  grouping,
59591
+ ...varyColors !== void 0 ? { varyColors } : {},
59592
+ ...firstSliceAngle !== void 0 ? { firstSliceAngle } : {},
59593
+ ...doughnutHoleSize !== void 0 ? { doughnutHoleSize } : {},
59594
+ ...barGapWidth !== void 0 ? { barGapWidth } : {},
59595
+ ...barOverlap !== void 0 ? { barOverlap } : {},
57802
59596
  chartPartPath,
57803
59597
  chartRelationshipId,
57804
59598
  ...dataTable ? { dataTable } : {},
@@ -57875,6 +59669,35 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57875
59669
  }
57876
59670
  return { categories, series };
57877
59671
  }
59672
+ /**
59673
+ * Read a numeric `@val` from a named child of a chart-type container.
59674
+ * Returns `undefined` when the child or its `@val` is absent/non-finite.
59675
+ */
59676
+ parseChartNumberVal(container, localName21) {
59677
+ const node = this.xmlLookupService.getChildByLocalName(container, localName21);
59678
+ const raw = node?.["@_val"];
59679
+ if (raw === void 0 || raw === null || raw === "") {
59680
+ return void 0;
59681
+ }
59682
+ const num = Number.parseFloat(String(raw));
59683
+ return Number.isFinite(num) ? num : void 0;
59684
+ }
59685
+ /**
59686
+ * Read a boolean `@val` from a named child of a chart-type container.
59687
+ * A present element with no `@val` follows the OOXML `CT_Boolean` default
59688
+ * of `true`; `undefined` when the child is absent.
59689
+ */
59690
+ parseChartBoolVal(container, localName21) {
59691
+ const node = this.xmlLookupService.getChildByLocalName(container, localName21);
59692
+ if (!node) {
59693
+ return void 0;
59694
+ }
59695
+ const raw = node["@_val"];
59696
+ if (raw === void 0 || raw === null || raw === "") {
59697
+ return true;
59698
+ }
59699
+ return !(raw === "0" || raw === "false");
59700
+ }
57878
59701
  /**
57879
59702
  * Build the series array from raw OOXML `c:ser` nodes.
57880
59703
  *
@@ -57918,6 +59741,10 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57918
59741
  );
57919
59742
  const dataLabels = parseSeriesDataLabels(seriesNode, this.xmlLookupService);
57920
59743
  const explosion = parseSeriesExplosion(seriesNode, this.xmlLookupService);
59744
+ const smoothNode = this.xmlLookupService.getChildByLocalName(seriesNode, "smooth");
59745
+ const smooth = smoothNode ? !(smoothNode["@_val"] === "0" || smoothNode["@_val"] === "false") : void 0;
59746
+ const invertNode = this.xmlLookupService.getChildByLocalName(seriesNode, "invertIfNegative");
59747
+ const invertIfNegative = invertNode ? !(invertNode["@_val"] === "0" || invertNode["@_val"] === "false") : void 0;
57921
59748
  return {
57922
59749
  name: seriesName.trim().length > 0 ? seriesName : `Series ${seriesIndex + 1}`,
57923
59750
  values: fallbackValues,
@@ -57928,6 +59755,8 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57928
59755
  ...seriesMarker ? { marker: seriesMarker } : {},
57929
59756
  ...dataLabels.length > 0 ? { dataLabels } : {},
57930
59757
  ...explosion !== void 0 ? { explosion } : {},
59758
+ ...invertIfNegative !== void 0 ? { invertIfNegative } : {},
59759
+ ...smooth !== void 0 ? { smooth } : {},
57931
59760
  ...axisId !== void 0 ? { axisId } : {},
57932
59761
  ...seriesChartType ? { seriesChartType } : {}
57933
59762
  };
@@ -58754,6 +60583,8 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58754
60583
  async buildLoadData(presentationState, slidesWithWarnings, slideMasters) {
58755
60584
  const headerFooter = this.extractHeaderFooter();
58756
60585
  const presentationProperties = await this.parsePresentationProperties();
60586
+ const viewProperties = await this.parseViewProperties();
60587
+ this.loadedViewProperties = viewProperties;
58757
60588
  const customShows = this.parseCustomShows();
58758
60589
  const tableStyleMap = await this.parseTableStyles();
58759
60590
  const embeddedFontList = parseEmbeddedFontList(this.presentationData);
@@ -58783,7 +60614,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58783
60614
  presentationState.height,
58784
60615
  this.rawSlideWidthEmu,
58785
60616
  this.rawSlideHeightEmu
58786
- ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withCustomShows(customShows).withSections(
60617
+ ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withViewProperties(viewProperties).withCustomShows(customShows).withSections(
58787
60618
  presentationState.orderedSections.length > 0 ? presentationState.orderedSections : void 0
58788
60619
  ).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(
58789
60620
  this.signatureDetection?.signatureCount && this.signatureDetection.signatureCount > 0 ? this.signatureDetection.signatureCount : void 0
@@ -58914,6 +60745,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58914
60745
  this.customXmlParts = [];
58915
60746
  this.loadedEmbeddedFonts = [];
58916
60747
  this.loadedEmbeddedFontList = void 0;
60748
+ this.loadedViewProperties = void 0;
58917
60749
  this.orderedSlidePaths = [];
58918
60750
  this.zip = null;
58919
60751
  }
@@ -59259,6 +61091,7 @@ var PptxHandlerRuntime95 = class _PptxHandlerRuntime extends PptxHandlerRuntime9
59259
61091
  });
59260
61092
  this.mediaDataParser = new PptxMediaDataParser({
59261
61093
  slideRelsMap: this.slideRelsMap,
61094
+ externalRelsMap: this.externalRelsMap,
59262
61095
  resolvePath: (base, relative) => this.resolvePath(base, relative),
59263
61096
  getPathExtension: (pathValue) => this.getPathExtension(pathValue)
59264
61097
  });