pptx-viewer-core 1.1.46 → 1.1.47

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
Binary file
Binary file
package/dist/index.d.mts CHANGED
@@ -2576,7 +2576,7 @@ declare function decomposeSmartArt(smartArtData: PptxSmartArtData, containerBoun
2576
2576
  * @module smartart-editing-node-ops
2577
2577
  */
2578
2578
 
2579
- /** Reset the edit counter (useful in tests). */
2579
+ /** No-op kept for API compatibility; id generation no longer needs a counter. */
2580
2580
  declare function resetSmartArtEditCounter(): void;
2581
2581
  /**
2582
2582
  * Add a new node to a SmartArt diagram after a given sibling.
@@ -2613,7 +2613,10 @@ declare function demoteSmartArtNode(data: PptxSmartArtData, nodeId: string): Ppt
2613
2613
  /**
2614
2614
  * Add a new node as a child of a given parent.
2615
2615
  *
2616
- * If `parentId` is undefined, the node is added as a root-level item.
2616
+ * If `parentId` is undefined, the node is added as a root-level item, using
2617
+ * the diagram's own root/doc id (inferred from an existing top-level node)
2618
+ * so it ends up as a sibling of the other top-level items rather than an
2619
+ * unparented node the save pipeline can't anchor into the diagram XML.
2617
2620
  * If `text` is undefined, a default label is generated.
2618
2621
  *
2619
2622
  * Returns a new PptxSmartArtData with the node inserted and
@@ -6737,14 +6740,6 @@ declare class PptxHandlerRuntime$V extends PptxHandlerRuntime$W {
6737
6740
  * carries no colour transform.
6738
6741
  */
6739
6742
  protected regenerateSmartArtColorPart(slidePath: string, smartArtData: SmartArtPptxElement['smartArtData']): Promise<void>;
6740
- /**
6741
- * Merge the in-memory quick style back into `ppt/diagrams/quickStyles*.xml`.
6742
- *
6743
- * Resolves the part via the SmartArt `styleRelId` relationship, merges
6744
- * surgically, and skips gracefully when the rel or part is absent. No-op
6745
- * when the in-memory data carries no quick style.
6746
- */
6747
- protected regenerateSmartArtQuickStylePart(slidePath: string, smartArtData: SmartArtPptxElement['smartArtData']): Promise<void>;
6748
6743
  /**
6749
6744
  * Read a SmartArt diagram part by slide relationship id, locate its root
6750
6745
  * definition element by local name, apply a surgical merge callback, and
package/dist/index.d.ts CHANGED
@@ -2576,7 +2576,7 @@ declare function decomposeSmartArt(smartArtData: PptxSmartArtData, containerBoun
2576
2576
  * @module smartart-editing-node-ops
2577
2577
  */
2578
2578
 
2579
- /** Reset the edit counter (useful in tests). */
2579
+ /** No-op kept for API compatibility; id generation no longer needs a counter. */
2580
2580
  declare function resetSmartArtEditCounter(): void;
2581
2581
  /**
2582
2582
  * Add a new node to a SmartArt diagram after a given sibling.
@@ -2613,7 +2613,10 @@ declare function demoteSmartArtNode(data: PptxSmartArtData, nodeId: string): Ppt
2613
2613
  /**
2614
2614
  * Add a new node as a child of a given parent.
2615
2615
  *
2616
- * If `parentId` is undefined, the node is added as a root-level item.
2616
+ * If `parentId` is undefined, the node is added as a root-level item, using
2617
+ * the diagram's own root/doc id (inferred from an existing top-level node)
2618
+ * so it ends up as a sibling of the other top-level items rather than an
2619
+ * unparented node the save pipeline can't anchor into the diagram XML.
2617
2620
  * If `text` is undefined, a default label is generated.
2618
2621
  *
2619
2622
  * Returns a new PptxSmartArtData with the node inserted and
@@ -6737,14 +6740,6 @@ declare class PptxHandlerRuntime$V extends PptxHandlerRuntime$W {
6737
6740
  * carries no colour transform.
6738
6741
  */
6739
6742
  protected regenerateSmartArtColorPart(slidePath: string, smartArtData: SmartArtPptxElement['smartArtData']): Promise<void>;
6740
- /**
6741
- * Merge the in-memory quick style back into `ppt/diagrams/quickStyles*.xml`.
6742
- *
6743
- * Resolves the part via the SmartArt `styleRelId` relationship, merges
6744
- * surgically, and skips gracefully when the rel or part is absent. No-op
6745
- * when the in-memory data carries no quick style.
6746
- */
6747
- protected regenerateSmartArtQuickStylePart(slidePath: string, smartArtData: SmartArtPptxElement['smartArtData']): Promise<void>;
6748
6743
  /**
6749
6744
  * Read a SmartArt diagram part by slide relationship id, locate its root
6750
6745
  * definition element by local name, apply a surgical merge callback, and
package/dist/index.js CHANGED
@@ -17952,12 +17952,19 @@ function resolveLayoutFromRawType(layoutType) {
17952
17952
  }
17953
17953
 
17954
17954
  // src/core/utils/smartart-editing-node-ops.ts
17955
- var editNodeCounter = 0;
17956
17955
  function nextModelId() {
17957
- return `smartart-node-${Date.now()}-${++editNodeCounter}`;
17956
+ return `{${generateFontGuid()}}`;
17958
17957
  }
17959
17958
  function resetSmartArtEditCounter() {
17960
- editNodeCounter = 0;
17959
+ }
17960
+ function findRootParentId(nodes) {
17961
+ const nodeIds = new Set(nodes.map((n) => n.id));
17962
+ for (const node of nodes) {
17963
+ if (node.parentId && !nodeIds.has(node.parentId)) {
17964
+ return node.parentId;
17965
+ }
17966
+ }
17967
+ return void 0;
17961
17968
  }
17962
17969
  function addSmartArtNode(data, text, afterNodeId) {
17963
17970
  const newId = nextModelId();
@@ -17966,6 +17973,7 @@ function addSmartArtNode(data, text, afterNodeId) {
17966
17973
  const sibling = data.nodes.find((n) => n.id === afterNodeId);
17967
17974
  parentId = sibling?.parentId;
17968
17975
  }
17976
+ parentId ??= findRootParentId(data.nodes);
17969
17977
  const newNode = {
17970
17978
  id: newId,
17971
17979
  text,
@@ -18118,19 +18126,20 @@ function demoteSmartArtNode(data, nodeId) {
18118
18126
  };
18119
18127
  }
18120
18128
  function addSmartArtNodeAsChild(data, parentId, text) {
18129
+ const resolvedParentId = parentId ?? findRootParentId(data.nodes);
18121
18130
  const newId = nextModelId();
18122
18131
  const label = text ?? `Item ${data.nodes.length + 1}`;
18123
18132
  const newNode = {
18124
18133
  id: newId,
18125
18134
  text: label,
18126
- parentId
18135
+ parentId: resolvedParentId
18127
18136
  };
18128
18137
  const nodes = [...data.nodes, newNode];
18129
18138
  const connections = [...data.connections ?? []];
18130
- if (parentId) {
18131
- const maxSrcOrd = connections.filter((c) => c.sourceId === parentId).reduce((max, c) => Math.max(max, c.srcOrd ?? 0), -1);
18139
+ if (resolvedParentId) {
18140
+ const maxSrcOrd = connections.filter((c) => c.sourceId === resolvedParentId).reduce((max, c) => Math.max(max, c.srcOrd ?? 0), -1);
18132
18141
  connections.push({
18133
- sourceId: parentId,
18142
+ sourceId: resolvedParentId,
18134
18143
  destId: newId,
18135
18144
  type: "parOf",
18136
18145
  srcOrd: maxSrcOrd + 1,
@@ -33444,12 +33453,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33444
33453
  return false;
33445
33454
  }
33446
33455
  let mutated = false;
33447
- if (transform.name && transform.name.length > 0) {
33448
- if (colorsDef["@_title"] !== transform.name) {
33449
- colorsDef["@_title"] = transform.name;
33450
- mutated = true;
33451
- }
33452
- }
33453
33456
  const styleLblKey = findKey11(colorsDef, "styleLbl", getLocalName);
33454
33457
  if (!styleLblKey) {
33455
33458
  return mutated;
@@ -33483,54 +33486,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33483
33486
  return mutated;
33484
33487
  }
33485
33488
 
33486
- // src/core/core/runtime/smartart-quickstyle-builder.ts
33487
- function applySmartArtQuickStyle(styleDef, quickStyle) {
33488
- if (!quickStyle || !quickStyle.name || quickStyle.name.length === 0) {
33489
- return false;
33490
- }
33491
- if (styleDef["@_title"] === quickStyle.name) {
33492
- return false;
33493
- }
33494
- styleDef["@_title"] = quickStyle.name;
33495
- return true;
33496
- }
33497
-
33498
- // src/core/core/runtime/smartart-save-chrome.ts
33499
- function asObject2(value) {
33500
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
33501
- }
33502
- function applySmartArtChrome(dataModel, chrome, getLocalName) {
33503
- if (!chrome || !chrome.backgroundColor && !chrome.outlineColor && (chrome.outlineWidth === null || chrome.outlineWidth === void 0)) {
33504
- return;
33505
- }
33506
- const findKey13 = (obj, name) => Object.keys(obj).find((k) => getLocalName(k) === name);
33507
- if (chrome.backgroundColor) {
33508
- const hex8 = chrome.backgroundColor.replace("#", "");
33509
- const bgKey = findKey13(dataModel, "bg") ?? "dgm:bg";
33510
- const bg = asObject2(dataModel[bgKey]);
33511
- const fillKey = findKey13(bg, "solidFill") ?? "a:solidFill";
33512
- bg[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33513
- dataModel[bgKey] = bg;
33514
- }
33515
- const hasOutlineWidth = chrome.outlineWidth !== null && chrome.outlineWidth !== void 0;
33516
- if (chrome.outlineColor || hasOutlineWidth) {
33517
- const wholeKey = findKey13(dataModel, "whole") ?? "dgm:whole";
33518
- const whole = asObject2(dataModel[wholeKey]);
33519
- const lnKey = findKey13(whole, "ln") ?? "a:ln";
33520
- const ln = asObject2(whole[lnKey]);
33521
- if (hasOutlineWidth) {
33522
- ln["@_w"] = String(Math.round(chrome.outlineWidth * 12700));
33523
- }
33524
- if (chrome.outlineColor) {
33525
- const hex8 = chrome.outlineColor.replace("#", "");
33526
- const fillKey = findKey13(ln, "solidFill") ?? "a:solidFill";
33527
- ln[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33528
- }
33529
- whole[lnKey] = ln;
33530
- dataModel[wholeKey] = whole;
33531
- }
33532
- }
33533
-
33534
33489
  // src/core/core/runtime/smartart-style-xml.ts
33535
33490
  function localName(key) {
33536
33491
  const idx = key.indexOf(":");
@@ -33785,9 +33740,58 @@ function mergeSmartArtPointXml(existingPts, nodes) {
33785
33740
  }
33786
33741
  return merged;
33787
33742
  }
33788
- function buildSmartArtConnectionXml(connections) {
33743
+ function newSmartArtGuid() {
33744
+ return `{${generateFontGuid()}}`;
33745
+ }
33746
+ function normalizeConnType(type) {
33747
+ return type && type !== "parOf" ? type : "";
33748
+ }
33749
+ function connectionKey(conn) {
33750
+ return [
33751
+ conn.srcId,
33752
+ conn.destId,
33753
+ normalizeConnType(conn.type),
33754
+ conn.srcOrd ?? "",
33755
+ conn.destOrd ?? ""
33756
+ ].join(" ");
33757
+ }
33758
+ function mergeSmartArtConnectionXml(existingCxns, connections) {
33759
+ const existingByKey = /* @__PURE__ */ new Map();
33760
+ for (const cxn of existingCxns) {
33761
+ if (!cxn || typeof cxn !== "object") {
33762
+ continue;
33763
+ }
33764
+ const srcOrdRaw = parseInt(String(cxn["@_srcOrd"] ?? ""), 10);
33765
+ const destOrdRaw = parseInt(String(cxn["@_destOrd"] ?? ""), 10);
33766
+ const key = connectionKey({
33767
+ srcId: String(cxn["@_srcId"] || ""),
33768
+ destId: String(cxn["@_destId"] || ""),
33769
+ type: cxn["@_type"] ? String(cxn["@_type"]) : void 0,
33770
+ srcOrd: Number.isFinite(srcOrdRaw) ? srcOrdRaw : void 0,
33771
+ destOrd: Number.isFinite(destOrdRaw) ? destOrdRaw : void 0
33772
+ });
33773
+ const queue = existingByKey.get(key);
33774
+ if (queue) {
33775
+ queue.push(cxn);
33776
+ } else {
33777
+ existingByKey.set(key, [cxn]);
33778
+ }
33779
+ }
33789
33780
  return connections.map((conn) => {
33781
+ const key = connectionKey({
33782
+ srcId: conn.sourceId,
33783
+ destId: conn.destId,
33784
+ type: conn.type,
33785
+ srcOrd: conn.srcOrd,
33786
+ destOrd: conn.destOrd
33787
+ });
33788
+ const queue = existingByKey.get(key);
33789
+ const match = queue?.shift();
33790
+ if (match) {
33791
+ return match;
33792
+ }
33790
33793
  const cxnNode = {
33794
+ "@_modelId": newSmartArtGuid(),
33791
33795
  "@_srcId": conn.sourceId,
33792
33796
  "@_destId": conn.destId
33793
33797
  };
@@ -33804,6 +33808,204 @@ function buildSmartArtConnectionXml(connections) {
33804
33808
  });
33805
33809
  }
33806
33810
 
33811
+ // src/core/core/runtime/smartart-node-synthesis.ts
33812
+ function prSetOf(pt2) {
33813
+ const prSet = pt2["dgm:prSet"];
33814
+ return prSet && typeof prSet === "object" && !Array.isArray(prSet) ? prSet : {};
33815
+ }
33816
+ function findPresPointForAssoc(pts, assocId) {
33817
+ return pts.find(
33818
+ (pt2) => pt2["@_type"] === "pres" && String(prSetOf(pt2)["@_presAssocID"] || "") === assocId
33819
+ );
33820
+ }
33821
+ function maxPresParOfOrd(cxns, srcId) {
33822
+ return cxns.filter((c) => c["@_type"] === "presParOf" && c["@_srcId"] === srcId).reduce((max, c) => Math.max(max, parseInt(String(c["@_srcOrd"] ?? ""), 10) || 0), -1);
33823
+ }
33824
+ function countNodePresPoints(pts) {
33825
+ return pts.filter((pt2) => pt2["@_type"] === "pres" && prSetOf(pt2)["@_presName"] === "node").length;
33826
+ }
33827
+ function emptyTextBody() {
33828
+ return { "a:bodyPr": {}, "a:lstStyle": {}, "a:p": { "a:endParaRPr": { "@_lang": "en-US" } } };
33829
+ }
33830
+ function buildContentPoint(node) {
33831
+ const pt2 = { "@_modelId": node.id };
33832
+ pt2["dgm:prSet"] = node.text ? {} : { "@_phldrT": "[Text]" };
33833
+ pt2["dgm:spPr"] = {};
33834
+ pt2["dgm:t"] = shouldRebuildFromRuns(node) ? buildPointFromRuns(node.runs) : buildPointText(node.text ?? "");
33835
+ return pt2;
33836
+ }
33837
+ function buildTransPoint(id, type) {
33838
+ return { "@_modelId": id, "@_type": type, "dgm:prSet": {}, "dgm:t": emptyTextBody() };
33839
+ }
33840
+ function buildPresNodePoint(id, assocId, idx, cnt) {
33841
+ return {
33842
+ "@_modelId": id,
33843
+ "@_type": "pres",
33844
+ "dgm:prSet": {
33845
+ "dgm:presLayoutVars": { "dgm:bulletEnabled": { "@_val": "1" } },
33846
+ "@_presAssocID": assocId,
33847
+ "@_presName": "node",
33848
+ "@_presStyleLbl": "node1",
33849
+ "@_presStyleIdx": String(idx),
33850
+ "@_presStyleCnt": String(cnt)
33851
+ },
33852
+ "dgm:spPr": {}
33853
+ };
33854
+ }
33855
+ function buildPresSibTransPoint(id, assocId) {
33856
+ return {
33857
+ "@_modelId": id,
33858
+ "@_type": "pres",
33859
+ "dgm:prSet": { "@_presAssocID": assocId, "@_presName": "sibTrans", "@_presStyleCnt": "0" },
33860
+ "dgm:spPr": {}
33861
+ };
33862
+ }
33863
+ function buildParOfConnection(srcId, destId, srcOrd, parTransId, sibTransId) {
33864
+ return {
33865
+ "@_modelId": newSmartArtGuid(),
33866
+ "@_srcId": srcId,
33867
+ "@_destId": destId,
33868
+ "@_srcOrd": String(srcOrd),
33869
+ "@_destOrd": "0",
33870
+ "@_parTransId": parTransId,
33871
+ "@_sibTransId": sibTransId
33872
+ };
33873
+ }
33874
+ function buildPresOfConnection(srcId, destId, presId) {
33875
+ return {
33876
+ "@_modelId": newSmartArtGuid(),
33877
+ "@_type": "presOf",
33878
+ "@_srcId": srcId,
33879
+ "@_destId": destId,
33880
+ "@_srcOrd": "0",
33881
+ "@_destOrd": "0",
33882
+ "@_presId": presId
33883
+ };
33884
+ }
33885
+ function buildPresParOfConnection(srcId, destId, srcOrd, presId) {
33886
+ return {
33887
+ "@_modelId": newSmartArtGuid(),
33888
+ "@_type": "presParOf",
33889
+ "@_srcId": srcId,
33890
+ "@_destId": destId,
33891
+ "@_srcOrd": String(srcOrd),
33892
+ "@_destOrd": "0",
33893
+ "@_presId": presId
33894
+ };
33895
+ }
33896
+ function synthesizeNewSmartArtStructuralPoints(existingPts, existingCxns, nodes, connections) {
33897
+ const existingContentIds = new Set(
33898
+ existingPts.filter(isContentPoint).map((pt2) => String(pt2["@_modelId"] || ""))
33899
+ );
33900
+ const newNodes = nodes.filter((n) => n.id && !existingContentIds.has(n.id));
33901
+ if (newNodes.length === 0) {
33902
+ return { pts: existingPts, cxns: existingCxns, extraConnections: [] };
33903
+ }
33904
+ const presId = existingCxns.find((c) => c["@_presId"])?.["@_presId"];
33905
+ if (!presId) {
33906
+ return { pts: existingPts, cxns: existingCxns, extraConnections: [] };
33907
+ }
33908
+ const pts = [...existingPts];
33909
+ const cxns = [...existingCxns];
33910
+ const extraConnections = [];
33911
+ const connectionByChildId = /* @__PURE__ */ new Map();
33912
+ for (const conn of connections ?? []) {
33913
+ if (!conn.type || conn.type === "parOf") {
33914
+ connectionByChildId.set(conn.destId, conn);
33915
+ }
33916
+ }
33917
+ for (const node of newNodes) {
33918
+ const parentId = node.parentId;
33919
+ const parentPres = parentId ? findPresPointForAssoc(pts, parentId) : void 0;
33920
+ if (!parentId || !parentPres) {
33921
+ continue;
33922
+ }
33923
+ const parTransId = newSmartArtGuid();
33924
+ const sibTransId = newSmartArtGuid();
33925
+ const presNodeId = newSmartArtGuid();
33926
+ const presSibTransId = newSmartArtGuid();
33927
+ pts.push(buildContentPoint(node));
33928
+ pts.push(buildTransPoint(parTransId, "parTrans"));
33929
+ pts.push(buildTransPoint(sibTransId, "sibTrans"));
33930
+ const idx = countNodePresPoints(pts);
33931
+ pts.push(buildPresNodePoint(presNodeId, node.id, idx, idx + 1));
33932
+ pts.push(buildPresSibTransPoint(presSibTransId, sibTransId));
33933
+ const total = idx + 1;
33934
+ for (const pt2 of pts) {
33935
+ if (pt2["@_type"] === "pres" && prSetOf(pt2)["@_presName"] === "node") {
33936
+ prSetOf(pt2)["@_presStyleCnt"] = String(total);
33937
+ }
33938
+ }
33939
+ const srcOrd = connectionByChildId.get(node.id)?.srcOrd ?? 0;
33940
+ cxns.push(buildParOfConnection(parentId, node.id, srcOrd, parTransId, sibTransId));
33941
+ cxns.push(buildPresOfConnection(node.id, presNodeId, presId));
33942
+ extraConnections.push({
33943
+ sourceId: node.id,
33944
+ destId: presNodeId,
33945
+ type: "presOf",
33946
+ srcOrd: 0,
33947
+ destOrd: 0
33948
+ });
33949
+ const parentPresId = String(parentPres["@_modelId"]);
33950
+ const baseOrd = maxPresParOfOrd(cxns, parentPresId) + 1;
33951
+ cxns.push(buildPresParOfConnection(parentPresId, presNodeId, baseOrd, presId));
33952
+ cxns.push(buildPresParOfConnection(parentPresId, presSibTransId, baseOrd + 1, presId));
33953
+ extraConnections.push(
33954
+ {
33955
+ sourceId: parentPresId,
33956
+ destId: presNodeId,
33957
+ type: "presParOf",
33958
+ srcOrd: baseOrd,
33959
+ destOrd: 0
33960
+ },
33961
+ {
33962
+ sourceId: parentPresId,
33963
+ destId: presSibTransId,
33964
+ type: "presParOf",
33965
+ srcOrd: baseOrd + 1,
33966
+ destOrd: 0
33967
+ }
33968
+ );
33969
+ }
33970
+ return { pts, cxns, extraConnections };
33971
+ }
33972
+
33973
+ // src/core/core/runtime/smartart-save-chrome.ts
33974
+ function asObject2(value) {
33975
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
33976
+ }
33977
+ function applySmartArtChrome(dataModel, chrome, getLocalName) {
33978
+ if (!chrome || !chrome.backgroundColor && !chrome.outlineColor && (chrome.outlineWidth === null || chrome.outlineWidth === void 0)) {
33979
+ return;
33980
+ }
33981
+ const findKey13 = (obj, name) => Object.keys(obj).find((k) => getLocalName(k) === name);
33982
+ if (chrome.backgroundColor) {
33983
+ const hex8 = chrome.backgroundColor.replace("#", "");
33984
+ const bgKey = findKey13(dataModel, "bg") ?? "dgm:bg";
33985
+ const bg = asObject2(dataModel[bgKey]);
33986
+ const fillKey = findKey13(bg, "solidFill") ?? "a:solidFill";
33987
+ bg[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33988
+ dataModel[bgKey] = bg;
33989
+ }
33990
+ const hasOutlineWidth = chrome.outlineWidth !== null && chrome.outlineWidth !== void 0;
33991
+ if (chrome.outlineColor || hasOutlineWidth) {
33992
+ const wholeKey = findKey13(dataModel, "whole") ?? "dgm:whole";
33993
+ const whole = asObject2(dataModel[wholeKey]);
33994
+ const lnKey = findKey13(whole, "ln") ?? "a:ln";
33995
+ const ln = asObject2(whole[lnKey]);
33996
+ if (hasOutlineWidth) {
33997
+ ln["@_w"] = String(Math.round(chrome.outlineWidth * 12700));
33998
+ }
33999
+ if (chrome.outlineColor) {
34000
+ const hex8 = chrome.outlineColor.replace("#", "");
34001
+ const fillKey = findKey13(ln, "solidFill") ?? "a:solidFill";
34002
+ ln[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
34003
+ }
34004
+ whole[lnKey] = ln;
34005
+ dataModel[wholeKey] = whole;
34006
+ }
34007
+ }
34008
+
33807
34009
  // src/core/core/runtime/PptxHandlerRuntimeSaveDocumentParts.ts
33808
34010
  var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime23 {
33809
34011
  /** Pending SmartArt data updates to process during save. */
@@ -33856,29 +34058,34 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33856
34058
  const ptListKey = Object.keys(dataModel).find(
33857
34059
  (k) => this.compatibilityService.getXmlLocalName(k) === "ptLst"
33858
34060
  );
33859
- if (ptListKey) {
33860
- const ptList = dataModel[ptListKey];
33861
- const ptKey = Object.keys(ptList || {}).find(
33862
- (k) => this.compatibilityService.getXmlLocalName(k) === "pt"
34061
+ const cxnListKey = Object.keys(dataModel).find(
34062
+ (k) => this.compatibilityService.getXmlLocalName(k) === "cxnLst"
34063
+ );
34064
+ const ptList = ptListKey ? dataModel[ptListKey] : void 0;
34065
+ const cxnList = cxnListKey ? dataModel[cxnListKey] : void 0;
34066
+ const ptKey = ptList ? Object.keys(ptList).find((k) => this.compatibilityService.getXmlLocalName(k) === "pt") : void 0;
34067
+ const cxnKey = cxnList ? Object.keys(cxnList).find((k) => this.compatibilityService.getXmlLocalName(k) === "cxn") : void 0;
34068
+ let existingPts = ptKey && ptList ? this.ensureArray(ptList[ptKey]) : [];
34069
+ let existingCxns = cxnKey && cxnList ? this.ensureArray(cxnList[cxnKey]) : [];
34070
+ let desiredConnections = smartArtData.connections;
34071
+ if (ptKey && cxnKey) {
34072
+ const synthesized = synthesizeNewSmartArtStructuralPoints(
34073
+ existingPts,
34074
+ existingCxns,
34075
+ smartArtData.nodes,
34076
+ smartArtData.connections
33863
34077
  );
33864
- if (ptKey) {
33865
- const existingPts = this.ensureArray(ptList[ptKey]);
33866
- ptList[ptKey] = mergeSmartArtPointXml(existingPts, smartArtData.nodes);
34078
+ existingPts = synthesized.pts;
34079
+ existingCxns = synthesized.cxns;
34080
+ if (synthesized.extraConnections.length > 0) {
34081
+ desiredConnections = [...desiredConnections ?? [], ...synthesized.extraConnections];
33867
34082
  }
33868
34083
  }
33869
- if (smartArtData.connections && smartArtData.connections.length > 0) {
33870
- const cxnListKey = Object.keys(dataModel).find(
33871
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxnLst"
33872
- );
33873
- if (cxnListKey) {
33874
- const cxnList = dataModel[cxnListKey];
33875
- const cxnKey = Object.keys(cxnList || {}).find(
33876
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxn"
33877
- );
33878
- if (cxnKey) {
33879
- cxnList[cxnKey] = buildSmartArtConnectionXml(smartArtData.connections);
33880
- }
33881
- }
34084
+ if (ptKey && ptList) {
34085
+ ptList[ptKey] = mergeSmartArtPointXml(existingPts, smartArtData.nodes);
34086
+ }
34087
+ if (cxnKey && cxnList && desiredConnections && desiredConnections.length > 0) {
34088
+ cxnList[cxnKey] = mergeSmartArtConnectionXml(existingCxns, desiredConnections);
33882
34089
  }
33883
34090
  applySmartArtChrome(
33884
34091
  dataModel,
@@ -33890,7 +34097,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33890
34097
  console.warn(`Failed to save SmartArt data at ${dataPartPath}:`, e);
33891
34098
  }
33892
34099
  await this.regenerateSmartArtColorPart(slidePath, smartArtData);
33893
- await this.regenerateSmartArtQuickStylePart(slidePath, smartArtData);
33894
34100
  }
33895
34101
  this.pendingSmartArtUpdates = void 0;
33896
34102
  }
@@ -33919,26 +34125,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33919
34125
  )
33920
34126
  );
33921
34127
  }
33922
- /**
33923
- * Merge the in-memory quick style back into `ppt/diagrams/quickStyles*.xml`.
33924
- *
33925
- * Resolves the part via the SmartArt `styleRelId` relationship, merges
33926
- * surgically, and skips gracefully when the rel or part is absent. No-op
33927
- * when the in-memory data carries no quick style.
33928
- */
33929
- async regenerateSmartArtQuickStylePart(slidePath, smartArtData) {
33930
- const quickStyle = smartArtData?.quickStyle;
33931
- if (!smartArtData?.styleRelId || !quickStyle) {
33932
- return;
33933
- }
33934
- await this.mergeSmartArtDiagramPart(
33935
- slidePath,
33936
- smartArtData.styleRelId,
33937
- "styleDef",
33938
- "quick style",
33939
- (styleDef) => applySmartArtQuickStyle(styleDef, quickStyle)
33940
- );
33941
- }
33942
34128
  /**
33943
34129
  * Read a SmartArt diagram part by slide relationship id, locate its root
33944
34130
  * definition element by local name, apply a surgical merge callback, and
@@ -44099,7 +44285,7 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44099
44285
  const pointList = this.xmlLookupService.getChildByLocalName(dataModel, "ptLst");
44100
44286
  const points2 = this.xmlLookupService.getChildrenArrayByLocalName(pointList, "pt");
44101
44287
  const { parsedConnections, parentByNodeId } = this.parseSmartArtConnections(dataModel);
44102
- const nodes = points2.map((point) => {
44288
+ const nodes = points2.filter(isContentPoint).map((point) => {
44103
44289
  const pointId = String(point?.["@_modelId"] || "").trim();
44104
44290
  if (pointId.length === 0) {
44105
44291
  return null;
@@ -44108,14 +44294,11 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44108
44294
  const textValues = [];
44109
44295
  this.collectLocalTextValues(point, "t", textValues);
44110
44296
  const resolvedText = textValues.find((entry) => entry.trim().length > 0);
44111
- if (!resolvedText) {
44112
- return null;
44113
- }
44114
44297
  const runs = this.extractSmartArtNodeRuns(point);
44115
44298
  const style = this.extractSmartArtNodeStyle(point);
44116
44299
  return {
44117
44300
  id: pointId,
44118
- text: resolvedText.trim(),
44301
+ text: resolvedText ? resolvedText.trim() : "",
44119
44302
  parentId: parentByNodeId.get(pointId),
44120
44303
  nodeType,
44121
44304
  runs,
package/dist/index.mjs CHANGED
@@ -17947,12 +17947,19 @@ function resolveLayoutFromRawType(layoutType) {
17947
17947
  }
17948
17948
 
17949
17949
  // src/core/utils/smartart-editing-node-ops.ts
17950
- var editNodeCounter = 0;
17951
17950
  function nextModelId() {
17952
- return `smartart-node-${Date.now()}-${++editNodeCounter}`;
17951
+ return `{${generateFontGuid()}}`;
17953
17952
  }
17954
17953
  function resetSmartArtEditCounter() {
17955
- editNodeCounter = 0;
17954
+ }
17955
+ function findRootParentId(nodes) {
17956
+ const nodeIds = new Set(nodes.map((n) => n.id));
17957
+ for (const node of nodes) {
17958
+ if (node.parentId && !nodeIds.has(node.parentId)) {
17959
+ return node.parentId;
17960
+ }
17961
+ }
17962
+ return void 0;
17956
17963
  }
17957
17964
  function addSmartArtNode(data, text, afterNodeId) {
17958
17965
  const newId = nextModelId();
@@ -17961,6 +17968,7 @@ function addSmartArtNode(data, text, afterNodeId) {
17961
17968
  const sibling = data.nodes.find((n) => n.id === afterNodeId);
17962
17969
  parentId = sibling?.parentId;
17963
17970
  }
17971
+ parentId ??= findRootParentId(data.nodes);
17964
17972
  const newNode = {
17965
17973
  id: newId,
17966
17974
  text,
@@ -18113,19 +18121,20 @@ function demoteSmartArtNode(data, nodeId) {
18113
18121
  };
18114
18122
  }
18115
18123
  function addSmartArtNodeAsChild(data, parentId, text) {
18124
+ const resolvedParentId = parentId ?? findRootParentId(data.nodes);
18116
18125
  const newId = nextModelId();
18117
18126
  const label = text ?? `Item ${data.nodes.length + 1}`;
18118
18127
  const newNode = {
18119
18128
  id: newId,
18120
18129
  text: label,
18121
- parentId
18130
+ parentId: resolvedParentId
18122
18131
  };
18123
18132
  const nodes = [...data.nodes, newNode];
18124
18133
  const connections = [...data.connections ?? []];
18125
- if (parentId) {
18126
- const maxSrcOrd = connections.filter((c) => c.sourceId === parentId).reduce((max, c) => Math.max(max, c.srcOrd ?? 0), -1);
18134
+ if (resolvedParentId) {
18135
+ const maxSrcOrd = connections.filter((c) => c.sourceId === resolvedParentId).reduce((max, c) => Math.max(max, c.srcOrd ?? 0), -1);
18127
18136
  connections.push({
18128
- sourceId: parentId,
18137
+ sourceId: resolvedParentId,
18129
18138
  destId: newId,
18130
18139
  type: "parOf",
18131
18140
  srcOrd: maxSrcOrd + 1,
@@ -33439,12 +33448,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33439
33448
  return false;
33440
33449
  }
33441
33450
  let mutated = false;
33442
- if (transform.name && transform.name.length > 0) {
33443
- if (colorsDef["@_title"] !== transform.name) {
33444
- colorsDef["@_title"] = transform.name;
33445
- mutated = true;
33446
- }
33447
- }
33448
33451
  const styleLblKey = findKey11(colorsDef, "styleLbl", getLocalName);
33449
33452
  if (!styleLblKey) {
33450
33453
  return mutated;
@@ -33478,54 +33481,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33478
33481
  return mutated;
33479
33482
  }
33480
33483
 
33481
- // src/core/core/runtime/smartart-quickstyle-builder.ts
33482
- function applySmartArtQuickStyle(styleDef, quickStyle) {
33483
- if (!quickStyle || !quickStyle.name || quickStyle.name.length === 0) {
33484
- return false;
33485
- }
33486
- if (styleDef["@_title"] === quickStyle.name) {
33487
- return false;
33488
- }
33489
- styleDef["@_title"] = quickStyle.name;
33490
- return true;
33491
- }
33492
-
33493
- // src/core/core/runtime/smartart-save-chrome.ts
33494
- function asObject2(value) {
33495
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
33496
- }
33497
- function applySmartArtChrome(dataModel, chrome, getLocalName) {
33498
- if (!chrome || !chrome.backgroundColor && !chrome.outlineColor && (chrome.outlineWidth === null || chrome.outlineWidth === void 0)) {
33499
- return;
33500
- }
33501
- const findKey13 = (obj, name) => Object.keys(obj).find((k) => getLocalName(k) === name);
33502
- if (chrome.backgroundColor) {
33503
- const hex8 = chrome.backgroundColor.replace("#", "");
33504
- const bgKey = findKey13(dataModel, "bg") ?? "dgm:bg";
33505
- const bg = asObject2(dataModel[bgKey]);
33506
- const fillKey = findKey13(bg, "solidFill") ?? "a:solidFill";
33507
- bg[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33508
- dataModel[bgKey] = bg;
33509
- }
33510
- const hasOutlineWidth = chrome.outlineWidth !== null && chrome.outlineWidth !== void 0;
33511
- if (chrome.outlineColor || hasOutlineWidth) {
33512
- const wholeKey = findKey13(dataModel, "whole") ?? "dgm:whole";
33513
- const whole = asObject2(dataModel[wholeKey]);
33514
- const lnKey = findKey13(whole, "ln") ?? "a:ln";
33515
- const ln = asObject2(whole[lnKey]);
33516
- if (hasOutlineWidth) {
33517
- ln["@_w"] = String(Math.round(chrome.outlineWidth * 12700));
33518
- }
33519
- if (chrome.outlineColor) {
33520
- const hex8 = chrome.outlineColor.replace("#", "");
33521
- const fillKey = findKey13(ln, "solidFill") ?? "a:solidFill";
33522
- ln[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33523
- }
33524
- whole[lnKey] = ln;
33525
- dataModel[wholeKey] = whole;
33526
- }
33527
- }
33528
-
33529
33484
  // src/core/core/runtime/smartart-style-xml.ts
33530
33485
  function localName(key) {
33531
33486
  const idx = key.indexOf(":");
@@ -33780,9 +33735,58 @@ function mergeSmartArtPointXml(existingPts, nodes) {
33780
33735
  }
33781
33736
  return merged;
33782
33737
  }
33783
- function buildSmartArtConnectionXml(connections) {
33738
+ function newSmartArtGuid() {
33739
+ return `{${generateFontGuid()}}`;
33740
+ }
33741
+ function normalizeConnType(type) {
33742
+ return type && type !== "parOf" ? type : "";
33743
+ }
33744
+ function connectionKey(conn) {
33745
+ return [
33746
+ conn.srcId,
33747
+ conn.destId,
33748
+ normalizeConnType(conn.type),
33749
+ conn.srcOrd ?? "",
33750
+ conn.destOrd ?? ""
33751
+ ].join(" ");
33752
+ }
33753
+ function mergeSmartArtConnectionXml(existingCxns, connections) {
33754
+ const existingByKey = /* @__PURE__ */ new Map();
33755
+ for (const cxn of existingCxns) {
33756
+ if (!cxn || typeof cxn !== "object") {
33757
+ continue;
33758
+ }
33759
+ const srcOrdRaw = parseInt(String(cxn["@_srcOrd"] ?? ""), 10);
33760
+ const destOrdRaw = parseInt(String(cxn["@_destOrd"] ?? ""), 10);
33761
+ const key = connectionKey({
33762
+ srcId: String(cxn["@_srcId"] || ""),
33763
+ destId: String(cxn["@_destId"] || ""),
33764
+ type: cxn["@_type"] ? String(cxn["@_type"]) : void 0,
33765
+ srcOrd: Number.isFinite(srcOrdRaw) ? srcOrdRaw : void 0,
33766
+ destOrd: Number.isFinite(destOrdRaw) ? destOrdRaw : void 0
33767
+ });
33768
+ const queue = existingByKey.get(key);
33769
+ if (queue) {
33770
+ queue.push(cxn);
33771
+ } else {
33772
+ existingByKey.set(key, [cxn]);
33773
+ }
33774
+ }
33784
33775
  return connections.map((conn) => {
33776
+ const key = connectionKey({
33777
+ srcId: conn.sourceId,
33778
+ destId: conn.destId,
33779
+ type: conn.type,
33780
+ srcOrd: conn.srcOrd,
33781
+ destOrd: conn.destOrd
33782
+ });
33783
+ const queue = existingByKey.get(key);
33784
+ const match = queue?.shift();
33785
+ if (match) {
33786
+ return match;
33787
+ }
33785
33788
  const cxnNode = {
33789
+ "@_modelId": newSmartArtGuid(),
33786
33790
  "@_srcId": conn.sourceId,
33787
33791
  "@_destId": conn.destId
33788
33792
  };
@@ -33799,6 +33803,204 @@ function buildSmartArtConnectionXml(connections) {
33799
33803
  });
33800
33804
  }
33801
33805
 
33806
+ // src/core/core/runtime/smartart-node-synthesis.ts
33807
+ function prSetOf(pt2) {
33808
+ const prSet = pt2["dgm:prSet"];
33809
+ return prSet && typeof prSet === "object" && !Array.isArray(prSet) ? prSet : {};
33810
+ }
33811
+ function findPresPointForAssoc(pts, assocId) {
33812
+ return pts.find(
33813
+ (pt2) => pt2["@_type"] === "pres" && String(prSetOf(pt2)["@_presAssocID"] || "") === assocId
33814
+ );
33815
+ }
33816
+ function maxPresParOfOrd(cxns, srcId) {
33817
+ return cxns.filter((c) => c["@_type"] === "presParOf" && c["@_srcId"] === srcId).reduce((max, c) => Math.max(max, parseInt(String(c["@_srcOrd"] ?? ""), 10) || 0), -1);
33818
+ }
33819
+ function countNodePresPoints(pts) {
33820
+ return pts.filter((pt2) => pt2["@_type"] === "pres" && prSetOf(pt2)["@_presName"] === "node").length;
33821
+ }
33822
+ function emptyTextBody() {
33823
+ return { "a:bodyPr": {}, "a:lstStyle": {}, "a:p": { "a:endParaRPr": { "@_lang": "en-US" } } };
33824
+ }
33825
+ function buildContentPoint(node) {
33826
+ const pt2 = { "@_modelId": node.id };
33827
+ pt2["dgm:prSet"] = node.text ? {} : { "@_phldrT": "[Text]" };
33828
+ pt2["dgm:spPr"] = {};
33829
+ pt2["dgm:t"] = shouldRebuildFromRuns(node) ? buildPointFromRuns(node.runs) : buildPointText(node.text ?? "");
33830
+ return pt2;
33831
+ }
33832
+ function buildTransPoint(id, type) {
33833
+ return { "@_modelId": id, "@_type": type, "dgm:prSet": {}, "dgm:t": emptyTextBody() };
33834
+ }
33835
+ function buildPresNodePoint(id, assocId, idx, cnt) {
33836
+ return {
33837
+ "@_modelId": id,
33838
+ "@_type": "pres",
33839
+ "dgm:prSet": {
33840
+ "dgm:presLayoutVars": { "dgm:bulletEnabled": { "@_val": "1" } },
33841
+ "@_presAssocID": assocId,
33842
+ "@_presName": "node",
33843
+ "@_presStyleLbl": "node1",
33844
+ "@_presStyleIdx": String(idx),
33845
+ "@_presStyleCnt": String(cnt)
33846
+ },
33847
+ "dgm:spPr": {}
33848
+ };
33849
+ }
33850
+ function buildPresSibTransPoint(id, assocId) {
33851
+ return {
33852
+ "@_modelId": id,
33853
+ "@_type": "pres",
33854
+ "dgm:prSet": { "@_presAssocID": assocId, "@_presName": "sibTrans", "@_presStyleCnt": "0" },
33855
+ "dgm:spPr": {}
33856
+ };
33857
+ }
33858
+ function buildParOfConnection(srcId, destId, srcOrd, parTransId, sibTransId) {
33859
+ return {
33860
+ "@_modelId": newSmartArtGuid(),
33861
+ "@_srcId": srcId,
33862
+ "@_destId": destId,
33863
+ "@_srcOrd": String(srcOrd),
33864
+ "@_destOrd": "0",
33865
+ "@_parTransId": parTransId,
33866
+ "@_sibTransId": sibTransId
33867
+ };
33868
+ }
33869
+ function buildPresOfConnection(srcId, destId, presId) {
33870
+ return {
33871
+ "@_modelId": newSmartArtGuid(),
33872
+ "@_type": "presOf",
33873
+ "@_srcId": srcId,
33874
+ "@_destId": destId,
33875
+ "@_srcOrd": "0",
33876
+ "@_destOrd": "0",
33877
+ "@_presId": presId
33878
+ };
33879
+ }
33880
+ function buildPresParOfConnection(srcId, destId, srcOrd, presId) {
33881
+ return {
33882
+ "@_modelId": newSmartArtGuid(),
33883
+ "@_type": "presParOf",
33884
+ "@_srcId": srcId,
33885
+ "@_destId": destId,
33886
+ "@_srcOrd": String(srcOrd),
33887
+ "@_destOrd": "0",
33888
+ "@_presId": presId
33889
+ };
33890
+ }
33891
+ function synthesizeNewSmartArtStructuralPoints(existingPts, existingCxns, nodes, connections) {
33892
+ const existingContentIds = new Set(
33893
+ existingPts.filter(isContentPoint).map((pt2) => String(pt2["@_modelId"] || ""))
33894
+ );
33895
+ const newNodes = nodes.filter((n) => n.id && !existingContentIds.has(n.id));
33896
+ if (newNodes.length === 0) {
33897
+ return { pts: existingPts, cxns: existingCxns, extraConnections: [] };
33898
+ }
33899
+ const presId = existingCxns.find((c) => c["@_presId"])?.["@_presId"];
33900
+ if (!presId) {
33901
+ return { pts: existingPts, cxns: existingCxns, extraConnections: [] };
33902
+ }
33903
+ const pts = [...existingPts];
33904
+ const cxns = [...existingCxns];
33905
+ const extraConnections = [];
33906
+ const connectionByChildId = /* @__PURE__ */ new Map();
33907
+ for (const conn of connections ?? []) {
33908
+ if (!conn.type || conn.type === "parOf") {
33909
+ connectionByChildId.set(conn.destId, conn);
33910
+ }
33911
+ }
33912
+ for (const node of newNodes) {
33913
+ const parentId = node.parentId;
33914
+ const parentPres = parentId ? findPresPointForAssoc(pts, parentId) : void 0;
33915
+ if (!parentId || !parentPres) {
33916
+ continue;
33917
+ }
33918
+ const parTransId = newSmartArtGuid();
33919
+ const sibTransId = newSmartArtGuid();
33920
+ const presNodeId = newSmartArtGuid();
33921
+ const presSibTransId = newSmartArtGuid();
33922
+ pts.push(buildContentPoint(node));
33923
+ pts.push(buildTransPoint(parTransId, "parTrans"));
33924
+ pts.push(buildTransPoint(sibTransId, "sibTrans"));
33925
+ const idx = countNodePresPoints(pts);
33926
+ pts.push(buildPresNodePoint(presNodeId, node.id, idx, idx + 1));
33927
+ pts.push(buildPresSibTransPoint(presSibTransId, sibTransId));
33928
+ const total = idx + 1;
33929
+ for (const pt2 of pts) {
33930
+ if (pt2["@_type"] === "pres" && prSetOf(pt2)["@_presName"] === "node") {
33931
+ prSetOf(pt2)["@_presStyleCnt"] = String(total);
33932
+ }
33933
+ }
33934
+ const srcOrd = connectionByChildId.get(node.id)?.srcOrd ?? 0;
33935
+ cxns.push(buildParOfConnection(parentId, node.id, srcOrd, parTransId, sibTransId));
33936
+ cxns.push(buildPresOfConnection(node.id, presNodeId, presId));
33937
+ extraConnections.push({
33938
+ sourceId: node.id,
33939
+ destId: presNodeId,
33940
+ type: "presOf",
33941
+ srcOrd: 0,
33942
+ destOrd: 0
33943
+ });
33944
+ const parentPresId = String(parentPres["@_modelId"]);
33945
+ const baseOrd = maxPresParOfOrd(cxns, parentPresId) + 1;
33946
+ cxns.push(buildPresParOfConnection(parentPresId, presNodeId, baseOrd, presId));
33947
+ cxns.push(buildPresParOfConnection(parentPresId, presSibTransId, baseOrd + 1, presId));
33948
+ extraConnections.push(
33949
+ {
33950
+ sourceId: parentPresId,
33951
+ destId: presNodeId,
33952
+ type: "presParOf",
33953
+ srcOrd: baseOrd,
33954
+ destOrd: 0
33955
+ },
33956
+ {
33957
+ sourceId: parentPresId,
33958
+ destId: presSibTransId,
33959
+ type: "presParOf",
33960
+ srcOrd: baseOrd + 1,
33961
+ destOrd: 0
33962
+ }
33963
+ );
33964
+ }
33965
+ return { pts, cxns, extraConnections };
33966
+ }
33967
+
33968
+ // src/core/core/runtime/smartart-save-chrome.ts
33969
+ function asObject2(value) {
33970
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
33971
+ }
33972
+ function applySmartArtChrome(dataModel, chrome, getLocalName) {
33973
+ if (!chrome || !chrome.backgroundColor && !chrome.outlineColor && (chrome.outlineWidth === null || chrome.outlineWidth === void 0)) {
33974
+ return;
33975
+ }
33976
+ const findKey13 = (obj, name) => Object.keys(obj).find((k) => getLocalName(k) === name);
33977
+ if (chrome.backgroundColor) {
33978
+ const hex8 = chrome.backgroundColor.replace("#", "");
33979
+ const bgKey = findKey13(dataModel, "bg") ?? "dgm:bg";
33980
+ const bg = asObject2(dataModel[bgKey]);
33981
+ const fillKey = findKey13(bg, "solidFill") ?? "a:solidFill";
33982
+ bg[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33983
+ dataModel[bgKey] = bg;
33984
+ }
33985
+ const hasOutlineWidth = chrome.outlineWidth !== null && chrome.outlineWidth !== void 0;
33986
+ if (chrome.outlineColor || hasOutlineWidth) {
33987
+ const wholeKey = findKey13(dataModel, "whole") ?? "dgm:whole";
33988
+ const whole = asObject2(dataModel[wholeKey]);
33989
+ const lnKey = findKey13(whole, "ln") ?? "a:ln";
33990
+ const ln = asObject2(whole[lnKey]);
33991
+ if (hasOutlineWidth) {
33992
+ ln["@_w"] = String(Math.round(chrome.outlineWidth * 12700));
33993
+ }
33994
+ if (chrome.outlineColor) {
33995
+ const hex8 = chrome.outlineColor.replace("#", "");
33996
+ const fillKey = findKey13(ln, "solidFill") ?? "a:solidFill";
33997
+ ln[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33998
+ }
33999
+ whole[lnKey] = ln;
34000
+ dataModel[wholeKey] = whole;
34001
+ }
34002
+ }
34003
+
33802
34004
  // src/core/core/runtime/PptxHandlerRuntimeSaveDocumentParts.ts
33803
34005
  var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime23 {
33804
34006
  /** Pending SmartArt data updates to process during save. */
@@ -33851,29 +34053,34 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33851
34053
  const ptListKey = Object.keys(dataModel).find(
33852
34054
  (k) => this.compatibilityService.getXmlLocalName(k) === "ptLst"
33853
34055
  );
33854
- if (ptListKey) {
33855
- const ptList = dataModel[ptListKey];
33856
- const ptKey = Object.keys(ptList || {}).find(
33857
- (k) => this.compatibilityService.getXmlLocalName(k) === "pt"
34056
+ const cxnListKey = Object.keys(dataModel).find(
34057
+ (k) => this.compatibilityService.getXmlLocalName(k) === "cxnLst"
34058
+ );
34059
+ const ptList = ptListKey ? dataModel[ptListKey] : void 0;
34060
+ const cxnList = cxnListKey ? dataModel[cxnListKey] : void 0;
34061
+ const ptKey = ptList ? Object.keys(ptList).find((k) => this.compatibilityService.getXmlLocalName(k) === "pt") : void 0;
34062
+ const cxnKey = cxnList ? Object.keys(cxnList).find((k) => this.compatibilityService.getXmlLocalName(k) === "cxn") : void 0;
34063
+ let existingPts = ptKey && ptList ? this.ensureArray(ptList[ptKey]) : [];
34064
+ let existingCxns = cxnKey && cxnList ? this.ensureArray(cxnList[cxnKey]) : [];
34065
+ let desiredConnections = smartArtData.connections;
34066
+ if (ptKey && cxnKey) {
34067
+ const synthesized = synthesizeNewSmartArtStructuralPoints(
34068
+ existingPts,
34069
+ existingCxns,
34070
+ smartArtData.nodes,
34071
+ smartArtData.connections
33858
34072
  );
33859
- if (ptKey) {
33860
- const existingPts = this.ensureArray(ptList[ptKey]);
33861
- ptList[ptKey] = mergeSmartArtPointXml(existingPts, smartArtData.nodes);
34073
+ existingPts = synthesized.pts;
34074
+ existingCxns = synthesized.cxns;
34075
+ if (synthesized.extraConnections.length > 0) {
34076
+ desiredConnections = [...desiredConnections ?? [], ...synthesized.extraConnections];
33862
34077
  }
33863
34078
  }
33864
- if (smartArtData.connections && smartArtData.connections.length > 0) {
33865
- const cxnListKey = Object.keys(dataModel).find(
33866
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxnLst"
33867
- );
33868
- if (cxnListKey) {
33869
- const cxnList = dataModel[cxnListKey];
33870
- const cxnKey = Object.keys(cxnList || {}).find(
33871
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxn"
33872
- );
33873
- if (cxnKey) {
33874
- cxnList[cxnKey] = buildSmartArtConnectionXml(smartArtData.connections);
33875
- }
33876
- }
34079
+ if (ptKey && ptList) {
34080
+ ptList[ptKey] = mergeSmartArtPointXml(existingPts, smartArtData.nodes);
34081
+ }
34082
+ if (cxnKey && cxnList && desiredConnections && desiredConnections.length > 0) {
34083
+ cxnList[cxnKey] = mergeSmartArtConnectionXml(existingCxns, desiredConnections);
33877
34084
  }
33878
34085
  applySmartArtChrome(
33879
34086
  dataModel,
@@ -33885,7 +34092,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33885
34092
  console.warn(`Failed to save SmartArt data at ${dataPartPath}:`, e);
33886
34093
  }
33887
34094
  await this.regenerateSmartArtColorPart(slidePath, smartArtData);
33888
- await this.regenerateSmartArtQuickStylePart(slidePath, smartArtData);
33889
34095
  }
33890
34096
  this.pendingSmartArtUpdates = void 0;
33891
34097
  }
@@ -33914,26 +34120,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33914
34120
  )
33915
34121
  );
33916
34122
  }
33917
- /**
33918
- * Merge the in-memory quick style back into `ppt/diagrams/quickStyles*.xml`.
33919
- *
33920
- * Resolves the part via the SmartArt `styleRelId` relationship, merges
33921
- * surgically, and skips gracefully when the rel or part is absent. No-op
33922
- * when the in-memory data carries no quick style.
33923
- */
33924
- async regenerateSmartArtQuickStylePart(slidePath, smartArtData) {
33925
- const quickStyle = smartArtData?.quickStyle;
33926
- if (!smartArtData?.styleRelId || !quickStyle) {
33927
- return;
33928
- }
33929
- await this.mergeSmartArtDiagramPart(
33930
- slidePath,
33931
- smartArtData.styleRelId,
33932
- "styleDef",
33933
- "quick style",
33934
- (styleDef) => applySmartArtQuickStyle(styleDef, quickStyle)
33935
- );
33936
- }
33937
34123
  /**
33938
34124
  * Read a SmartArt diagram part by slide relationship id, locate its root
33939
34125
  * definition element by local name, apply a surgical merge callback, and
@@ -44094,7 +44280,7 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44094
44280
  const pointList = this.xmlLookupService.getChildByLocalName(dataModel, "ptLst");
44095
44281
  const points2 = this.xmlLookupService.getChildrenArrayByLocalName(pointList, "pt");
44096
44282
  const { parsedConnections, parentByNodeId } = this.parseSmartArtConnections(dataModel);
44097
- const nodes = points2.map((point) => {
44283
+ const nodes = points2.filter(isContentPoint).map((point) => {
44098
44284
  const pointId = String(point?.["@_modelId"] || "").trim();
44099
44285
  if (pointId.length === 0) {
44100
44286
  return null;
@@ -44103,14 +44289,11 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44103
44289
  const textValues = [];
44104
44290
  this.collectLocalTextValues(point, "t", textValues);
44105
44291
  const resolvedText = textValues.find((entry) => entry.trim().length > 0);
44106
- if (!resolvedText) {
44107
- return null;
44108
- }
44109
44292
  const runs = this.extractSmartArtNodeRuns(point);
44110
44293
  const style = this.extractSmartArtNodeStyle(point);
44111
44294
  return {
44112
44295
  id: pointId,
44113
- text: resolvedText.trim(),
44296
+ text: resolvedText ? resolvedText.trim() : "",
44114
44297
  parentId: parentByNodeId.get(pointId),
44115
44298
  nodeType,
44116
44299
  runs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-viewer-core",
3
- "version": "1.1.46",
3
+ "version": "1.1.47",
4
4
  "description": "PowerPoint PPTX engine: parse, edit, serialize, and convert .pptx files. Framework-agnostic TypeScript SDK.",
5
5
  "keywords": [
6
6
  "converter",