pptx-viewer-core 1.1.45 → 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/CHANGELOG.md CHANGED
@@ -8,6 +8,7 @@ by [git-cliff](https://git-cliff.org); do not edit it by hand.
8
8
 
9
9
  ### Bug Fixes
10
10
 
11
+ - **core:** Correct install docs and drop the retired @christophervr/pptx-viewer alias (by @ChristopherVR) ([6544b4e](https://github.com/ChristopherVR/pptx-viewer/commit/6544b4eaf086945ecd8a18b877de5a483032aa14))
11
12
  - **core,angular:** Revert xmldom to 0.8.x and fix shared import specifiers (by @ChristopherVR) ([29eda31](https://github.com/ChristopherVR/pptx-viewer/commit/29eda3119836559b63bc08733dd9dd6398a69c8d))
12
13
 
13
14
  ## [1.1.42](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-viewer-core@1.1.42) - 2026-06-27
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,
@@ -20278,7 +20287,12 @@ function switchSmartArtLayout(currentData, newLayoutType) {
20278
20287
  layoutType: newLayoutType,
20279
20288
  resolvedLayoutType: newLayoutType,
20280
20289
  // Clear the named layout preset — switching category invalidates it
20281
- layout: void 0
20290
+ layout: void 0,
20291
+ // Clear stale pre-computed drawing shapes from the old layout so the
20292
+ // reflow pipeline (rebuildDrawingShapesIfCleared) regenerates them for
20293
+ // the new layout type; otherwise the renderer keeps preferring the old
20294
+ // shapes and the switch has no visible effect.
20295
+ drawingShapes: void 0
20282
20296
  // Preserve everything else: nodes, connections, colours, styles, chrome, etc.
20283
20297
  };
20284
20298
  }
@@ -33439,12 +33453,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33439
33453
  return false;
33440
33454
  }
33441
33455
  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
33456
  const styleLblKey = findKey11(colorsDef, "styleLbl", getLocalName);
33449
33457
  if (!styleLblKey) {
33450
33458
  return mutated;
@@ -33478,54 +33486,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33478
33486
  return mutated;
33479
33487
  }
33480
33488
 
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
33489
  // src/core/core/runtime/smartart-style-xml.ts
33530
33490
  function localName(key) {
33531
33491
  const idx = key.indexOf(":");
@@ -33780,9 +33740,58 @@ function mergeSmartArtPointXml(existingPts, nodes) {
33780
33740
  }
33781
33741
  return merged;
33782
33742
  }
33783
- 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
+ }
33784
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
+ }
33785
33793
  const cxnNode = {
33794
+ "@_modelId": newSmartArtGuid(),
33786
33795
  "@_srcId": conn.sourceId,
33787
33796
  "@_destId": conn.destId
33788
33797
  };
@@ -33799,6 +33808,204 @@ function buildSmartArtConnectionXml(connections) {
33799
33808
  });
33800
33809
  }
33801
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
+
33802
34009
  // src/core/core/runtime/PptxHandlerRuntimeSaveDocumentParts.ts
33803
34010
  var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime23 {
33804
34011
  /** Pending SmartArt data updates to process during save. */
@@ -33851,29 +34058,34 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33851
34058
  const ptListKey = Object.keys(dataModel).find(
33852
34059
  (k) => this.compatibilityService.getXmlLocalName(k) === "ptLst"
33853
34060
  );
33854
- if (ptListKey) {
33855
- const ptList = dataModel[ptListKey];
33856
- const ptKey = Object.keys(ptList || {}).find(
33857
- (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
33858
34077
  );
33859
- if (ptKey) {
33860
- const existingPts = this.ensureArray(ptList[ptKey]);
33861
- 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];
33862
34082
  }
33863
34083
  }
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
- }
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);
33877
34089
  }
33878
34090
  applySmartArtChrome(
33879
34091
  dataModel,
@@ -33885,7 +34097,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33885
34097
  console.warn(`Failed to save SmartArt data at ${dataPartPath}:`, e);
33886
34098
  }
33887
34099
  await this.regenerateSmartArtColorPart(slidePath, smartArtData);
33888
- await this.regenerateSmartArtQuickStylePart(slidePath, smartArtData);
33889
34100
  }
33890
34101
  this.pendingSmartArtUpdates = void 0;
33891
34102
  }
@@ -33914,26 +34125,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33914
34125
  )
33915
34126
  );
33916
34127
  }
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
34128
  /**
33938
34129
  * Read a SmartArt diagram part by slide relationship id, locate its root
33939
34130
  * definition element by local name, apply a surgical merge callback, and
@@ -44094,7 +44285,7 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44094
44285
  const pointList = this.xmlLookupService.getChildByLocalName(dataModel, "ptLst");
44095
44286
  const points2 = this.xmlLookupService.getChildrenArrayByLocalName(pointList, "pt");
44096
44287
  const { parsedConnections, parentByNodeId } = this.parseSmartArtConnections(dataModel);
44097
- const nodes = points2.map((point) => {
44288
+ const nodes = points2.filter(isContentPoint).map((point) => {
44098
44289
  const pointId = String(point?.["@_modelId"] || "").trim();
44099
44290
  if (pointId.length === 0) {
44100
44291
  return null;
@@ -44103,14 +44294,11 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44103
44294
  const textValues = [];
44104
44295
  this.collectLocalTextValues(point, "t", textValues);
44105
44296
  const resolvedText = textValues.find((entry) => entry.trim().length > 0);
44106
- if (!resolvedText) {
44107
- return null;
44108
- }
44109
44297
  const runs = this.extractSmartArtNodeRuns(point);
44110
44298
  const style = this.extractSmartArtNodeStyle(point);
44111
44299
  return {
44112
44300
  id: pointId,
44113
- text: resolvedText.trim(),
44301
+ text: resolvedText ? resolvedText.trim() : "",
44114
44302
  parentId: parentByNodeId.get(pointId),
44115
44303
  nodeType,
44116
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,
@@ -20273,7 +20282,12 @@ function switchSmartArtLayout(currentData, newLayoutType) {
20273
20282
  layoutType: newLayoutType,
20274
20283
  resolvedLayoutType: newLayoutType,
20275
20284
  // Clear the named layout preset — switching category invalidates it
20276
- layout: void 0
20285
+ layout: void 0,
20286
+ // Clear stale pre-computed drawing shapes from the old layout so the
20287
+ // reflow pipeline (rebuildDrawingShapesIfCleared) regenerates them for
20288
+ // the new layout type; otherwise the renderer keeps preferring the old
20289
+ // shapes and the switch has no visible effect.
20290
+ drawingShapes: void 0
20277
20291
  // Preserve everything else: nodes, connections, colours, styles, chrome, etc.
20278
20292
  };
20279
20293
  }
@@ -33434,12 +33448,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33434
33448
  return false;
33435
33449
  }
33436
33450
  let mutated = false;
33437
- if (transform.name && transform.name.length > 0) {
33438
- if (colorsDef["@_title"] !== transform.name) {
33439
- colorsDef["@_title"] = transform.name;
33440
- mutated = true;
33441
- }
33442
- }
33443
33451
  const styleLblKey = findKey11(colorsDef, "styleLbl", getLocalName);
33444
33452
  if (!styleLblKey) {
33445
33453
  return mutated;
@@ -33473,54 +33481,6 @@ function applySmartArtColorTransform(colorsDef, transform, getLocalName) {
33473
33481
  return mutated;
33474
33482
  }
33475
33483
 
33476
- // src/core/core/runtime/smartart-quickstyle-builder.ts
33477
- function applySmartArtQuickStyle(styleDef, quickStyle) {
33478
- if (!quickStyle || !quickStyle.name || quickStyle.name.length === 0) {
33479
- return false;
33480
- }
33481
- if (styleDef["@_title"] === quickStyle.name) {
33482
- return false;
33483
- }
33484
- styleDef["@_title"] = quickStyle.name;
33485
- return true;
33486
- }
33487
-
33488
- // src/core/core/runtime/smartart-save-chrome.ts
33489
- function asObject2(value) {
33490
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
33491
- }
33492
- function applySmartArtChrome(dataModel, chrome, getLocalName) {
33493
- if (!chrome || !chrome.backgroundColor && !chrome.outlineColor && (chrome.outlineWidth === null || chrome.outlineWidth === void 0)) {
33494
- return;
33495
- }
33496
- const findKey13 = (obj, name) => Object.keys(obj).find((k) => getLocalName(k) === name);
33497
- if (chrome.backgroundColor) {
33498
- const hex8 = chrome.backgroundColor.replace("#", "");
33499
- const bgKey = findKey13(dataModel, "bg") ?? "dgm:bg";
33500
- const bg = asObject2(dataModel[bgKey]);
33501
- const fillKey = findKey13(bg, "solidFill") ?? "a:solidFill";
33502
- bg[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33503
- dataModel[bgKey] = bg;
33504
- }
33505
- const hasOutlineWidth = chrome.outlineWidth !== null && chrome.outlineWidth !== void 0;
33506
- if (chrome.outlineColor || hasOutlineWidth) {
33507
- const wholeKey = findKey13(dataModel, "whole") ?? "dgm:whole";
33508
- const whole = asObject2(dataModel[wholeKey]);
33509
- const lnKey = findKey13(whole, "ln") ?? "a:ln";
33510
- const ln = asObject2(whole[lnKey]);
33511
- if (hasOutlineWidth) {
33512
- ln["@_w"] = String(Math.round(chrome.outlineWidth * 12700));
33513
- }
33514
- if (chrome.outlineColor) {
33515
- const hex8 = chrome.outlineColor.replace("#", "");
33516
- const fillKey = findKey13(ln, "solidFill") ?? "a:solidFill";
33517
- ln[fillKey] = { "a:srgbClr": { "@_val": hex8 } };
33518
- }
33519
- whole[lnKey] = ln;
33520
- dataModel[wholeKey] = whole;
33521
- }
33522
- }
33523
-
33524
33484
  // src/core/core/runtime/smartart-style-xml.ts
33525
33485
  function localName(key) {
33526
33486
  const idx = key.indexOf(":");
@@ -33775,9 +33735,58 @@ function mergeSmartArtPointXml(existingPts, nodes) {
33775
33735
  }
33776
33736
  return merged;
33777
33737
  }
33778
- 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
+ }
33779
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
+ }
33780
33788
  const cxnNode = {
33789
+ "@_modelId": newSmartArtGuid(),
33781
33790
  "@_srcId": conn.sourceId,
33782
33791
  "@_destId": conn.destId
33783
33792
  };
@@ -33794,6 +33803,204 @@ function buildSmartArtConnectionXml(connections) {
33794
33803
  });
33795
33804
  }
33796
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
+
33797
34004
  // src/core/core/runtime/PptxHandlerRuntimeSaveDocumentParts.ts
33798
34005
  var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime23 {
33799
34006
  /** Pending SmartArt data updates to process during save. */
@@ -33846,29 +34053,34 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33846
34053
  const ptListKey = Object.keys(dataModel).find(
33847
34054
  (k) => this.compatibilityService.getXmlLocalName(k) === "ptLst"
33848
34055
  );
33849
- if (ptListKey) {
33850
- const ptList = dataModel[ptListKey];
33851
- const ptKey = Object.keys(ptList || {}).find(
33852
- (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
33853
34072
  );
33854
- if (ptKey) {
33855
- const existingPts = this.ensureArray(ptList[ptKey]);
33856
- 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];
33857
34077
  }
33858
34078
  }
33859
- if (smartArtData.connections && smartArtData.connections.length > 0) {
33860
- const cxnListKey = Object.keys(dataModel).find(
33861
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxnLst"
33862
- );
33863
- if (cxnListKey) {
33864
- const cxnList = dataModel[cxnListKey];
33865
- const cxnKey = Object.keys(cxnList || {}).find(
33866
- (k) => this.compatibilityService.getXmlLocalName(k) === "cxn"
33867
- );
33868
- if (cxnKey) {
33869
- cxnList[cxnKey] = buildSmartArtConnectionXml(smartArtData.connections);
33870
- }
33871
- }
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);
33872
34084
  }
33873
34085
  applySmartArtChrome(
33874
34086
  dataModel,
@@ -33880,7 +34092,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33880
34092
  console.warn(`Failed to save SmartArt data at ${dataPartPath}:`, e);
33881
34093
  }
33882
34094
  await this.regenerateSmartArtColorPart(slidePath, smartArtData);
33883
- await this.regenerateSmartArtQuickStylePart(slidePath, smartArtData);
33884
34095
  }
33885
34096
  this.pendingSmartArtUpdates = void 0;
33886
34097
  }
@@ -33909,26 +34120,6 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
33909
34120
  )
33910
34121
  );
33911
34122
  }
33912
- /**
33913
- * Merge the in-memory quick style back into `ppt/diagrams/quickStyles*.xml`.
33914
- *
33915
- * Resolves the part via the SmartArt `styleRelId` relationship, merges
33916
- * surgically, and skips gracefully when the rel or part is absent. No-op
33917
- * when the in-memory data carries no quick style.
33918
- */
33919
- async regenerateSmartArtQuickStylePart(slidePath, smartArtData) {
33920
- const quickStyle = smartArtData?.quickStyle;
33921
- if (!smartArtData?.styleRelId || !quickStyle) {
33922
- return;
33923
- }
33924
- await this.mergeSmartArtDiagramPart(
33925
- slidePath,
33926
- smartArtData.styleRelId,
33927
- "styleDef",
33928
- "quick style",
33929
- (styleDef) => applySmartArtQuickStyle(styleDef, quickStyle)
33930
- );
33931
- }
33932
34123
  /**
33933
34124
  * Read a SmartArt diagram part by slide relationship id, locate its root
33934
34125
  * definition element by local name, apply a surgical merge callback, and
@@ -44089,7 +44280,7 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44089
44280
  const pointList = this.xmlLookupService.getChildByLocalName(dataModel, "ptLst");
44090
44281
  const points2 = this.xmlLookupService.getChildrenArrayByLocalName(pointList, "pt");
44091
44282
  const { parsedConnections, parentByNodeId } = this.parseSmartArtConnections(dataModel);
44092
- const nodes = points2.map((point) => {
44283
+ const nodes = points2.filter(isContentPoint).map((point) => {
44093
44284
  const pointId = String(point?.["@_modelId"] || "").trim();
44094
44285
  if (pointId.length === 0) {
44095
44286
  return null;
@@ -44098,14 +44289,11 @@ var PptxHandlerRuntime70 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
44098
44289
  const textValues = [];
44099
44290
  this.collectLocalTextValues(point, "t", textValues);
44100
44291
  const resolvedText = textValues.find((entry) => entry.trim().length > 0);
44101
- if (!resolvedText) {
44102
- return null;
44103
- }
44104
44292
  const runs = this.extractSmartArtNodeRuns(point);
44105
44293
  const style = this.extractSmartArtNodeStyle(point);
44106
44294
  return {
44107
44295
  id: pointId,
44108
- text: resolvedText.trim(),
44296
+ text: resolvedText ? resolvedText.trim() : "",
44109
44297
  parentId: parentByNodeId.get(pointId),
44110
44298
  nodeType,
44111
44299
  runs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-viewer-core",
3
- "version": "1.1.45",
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",