pptx-viewer-core 1.2.1 → 1.2.3

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
@@ -4,6 +4,10 @@ All notable changes to this project are documented here.
4
4
  This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
5
5
  by [git-cliff](https://git-cliff.org); do not edit it by hand.
6
6
 
7
+ ## [1.2.2](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-viewer-core@1.2.2) - 2026-07-07
8
+
9
+ ## [1.2.1](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-viewer-core@1.2.1) - 2026-07-06
10
+
7
11
  ## [1.2.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-viewer-core@1.2.0) - 2026-07-05
8
12
 
9
13
  ### Features
package/README.md CHANGED
@@ -20,7 +20,7 @@ There is no UI here: this is the engine on its own. Use it directly when you nee
20
20
  npm install pptx-viewer-core
21
21
  ```
22
22
 
23
- > That's it, nothing else to install. **jszip** (a `.pptx` is a ZIP file, and this reads and writes that container) and **fast-xml-parser** (the slides inside are XML, and this reads and writes it) are regular dependencies of `pptx-viewer-core`, so your package manager pulls them in automatically. Password protection and digital signatures need a few extra packages (`node-forge`, `xml-crypto`, `@xmldom/xmldom`), but only if you actually use those features.
23
+ > That's it, nothing else to install. All runtime dependencies are pulled in automatically by your package manager. Password protection and digital signatures need a few extra packages (`node-forge`, `xml-crypto`, `@xmldom/xmldom`), but only if you actually use those features.
24
24
 
25
25
  ## What it does
26
26
 
package/dist/cli/index.js CHANGED
Binary file
Binary file
package/dist/index.d.mts CHANGED
@@ -2594,7 +2594,11 @@ declare function addSmartArtNode(data: PptxSmartArtData, text: string, afterNode
2594
2594
  declare function removeSmartArtNode(data: PptxSmartArtData, nodeId: string): PptxSmartArtData;
2595
2595
  /**
2596
2596
  * Update the text of a SmartArt node by ID.
2597
- * Clears drawing shapes to trigger layout reflow.
2597
+ *
2598
+ * When drawing shapes exist, updates the matching shape's text in-place so the
2599
+ * renderer path does not change (avoids polygon-to-chevron downgrade that makes
2600
+ * a pyramid look like stacked bars). When no drawing shapes are present the
2601
+ * family renderer reads text directly from the node array.
2598
2602
  */
2599
2603
  declare function updateSmartArtNodeText(data: PptxSmartArtData, nodeId: string, newText: string): PptxSmartArtData;
2600
2604
  /**
package/dist/index.d.ts CHANGED
@@ -2594,7 +2594,11 @@ declare function addSmartArtNode(data: PptxSmartArtData, text: string, afterNode
2594
2594
  declare function removeSmartArtNode(data: PptxSmartArtData, nodeId: string): PptxSmartArtData;
2595
2595
  /**
2596
2596
  * Update the text of a SmartArt node by ID.
2597
- * Clears drawing shapes to trigger layout reflow.
2597
+ *
2598
+ * When drawing shapes exist, updates the matching shape's text in-place so the
2599
+ * renderer path does not change (avoids polygon-to-chevron downgrade that makes
2600
+ * a pyramid look like stacked bars). When no drawing shapes are present the
2601
+ * family renderer reads text directly from the node array.
2598
2602
  */
2599
2603
  declare function updateSmartArtNodeText(data: PptxSmartArtData, nodeId: string, newText: string): PptxSmartArtData;
2600
2604
  /**
package/dist/index.js CHANGED
@@ -17952,6 +17952,9 @@ function resolveLayoutFromRawType(layoutType) {
17952
17952
  }
17953
17953
 
17954
17954
  // src/core/utils/smartart-editing-node-ops.ts
17955
+ function markShapesStale(shapes) {
17956
+ return shapes !== void 0 && shapes.length > 0 ? [] : void 0;
17957
+ }
17955
17958
  function nextModelId() {
17956
17959
  return `{${generateFontGuid()}}`;
17957
17960
  }
@@ -18005,8 +18008,7 @@ function addSmartArtNode(data, text, afterNodeId) {
18005
18008
  ...data,
18006
18009
  nodes,
18007
18010
  connections: connections.length > 0 ? connections : void 0,
18008
- // Clear pre-computed shapes to force layout reflow
18009
- drawingShapes: void 0
18011
+ drawingShapes: markShapesStale(data.drawingShapes)
18010
18012
  };
18011
18013
  }
18012
18014
  function removeSmartArtNode(data, nodeId) {
@@ -18035,7 +18037,7 @@ function removeSmartArtNode(data, nodeId) {
18035
18037
  ...data,
18036
18038
  nodes,
18037
18039
  connections: connections.length > 0 ? connections : void 0,
18038
- drawingShapes: void 0
18040
+ drawingShapes: markShapesStale(data.drawingShapes)
18039
18041
  };
18040
18042
  }
18041
18043
  function updateSmartArtNodeText(data, nodeId, newText) {
@@ -18043,9 +18045,48 @@ function updateSmartArtNodeText(data, nodeId, newText) {
18043
18045
  return {
18044
18046
  ...data,
18045
18047
  nodes,
18046
- drawingShapes: void 0
18048
+ drawingShapes: patchDrawingShapeText(data.drawingShapes, data.nodes, nodeId, newText)
18047
18049
  };
18048
18050
  }
18051
+ function patchDrawingShapeText(shapes, nodes, nodeId, newText) {
18052
+ if (!shapes || shapes.length === 0) {
18053
+ return shapes;
18054
+ }
18055
+ const idx = findDrawingShapeIndex(shapes, nodes, nodeId);
18056
+ if (idx < 0) {
18057
+ return [];
18058
+ }
18059
+ const updated = [...shapes];
18060
+ updated[idx] = { ...updated[idx], text: newText };
18061
+ return updated;
18062
+ }
18063
+ function findDrawingShapeIndex(shapes, nodes, nodeId) {
18064
+ for (let i = 0; i < shapes.length; i++) {
18065
+ if (shapes[i].id.startsWith("reflow-") && shapes[i].id.endsWith(`-${nodeId}`)) {
18066
+ return i;
18067
+ }
18068
+ }
18069
+ if (shapes.length === nodes.length) {
18070
+ const nodeIdx = nodes.findIndex((n) => n.id === nodeId);
18071
+ if (nodeIdx >= 0) {
18072
+ return nodeIdx;
18073
+ }
18074
+ }
18075
+ const node = nodes.find((n) => n.id === nodeId);
18076
+ if (node?.text) {
18077
+ const text = node.text.trim();
18078
+ const matches = [];
18079
+ for (let i = 0; i < shapes.length; i++) {
18080
+ if (shapes[i].text?.trim() === text) {
18081
+ matches.push(i);
18082
+ }
18083
+ }
18084
+ if (matches.length === 1) {
18085
+ return matches[0];
18086
+ }
18087
+ }
18088
+ return -1;
18089
+ }
18049
18090
  function reorderSmartArtNode(data, nodeId, direction) {
18050
18091
  const node = data.nodes.find((n) => n.id === nodeId);
18051
18092
  if (!node) {
@@ -18068,7 +18109,7 @@ function reorderSmartArtNode(data, nodeId, direction) {
18068
18109
  return {
18069
18110
  ...data,
18070
18111
  nodes,
18071
- drawingShapes: void 0
18112
+ drawingShapes: markShapesStale(data.drawingShapes)
18072
18113
  };
18073
18114
  }
18074
18115
  function promoteSmartArtNode(data, nodeId) {
@@ -18095,7 +18136,7 @@ function promoteSmartArtNode(data, nodeId) {
18095
18136
  ...data,
18096
18137
  nodes,
18097
18138
  connections: connections.length > 0 ? connections : void 0,
18098
- drawingShapes: void 0
18139
+ drawingShapes: markShapesStale(data.drawingShapes)
18099
18140
  };
18100
18141
  }
18101
18142
  function demoteSmartArtNode(data, nodeId) {
@@ -18122,7 +18163,7 @@ function demoteSmartArtNode(data, nodeId) {
18122
18163
  ...data,
18123
18164
  nodes,
18124
18165
  connections: connections.length > 0 ? connections : void 0,
18125
- drawingShapes: void 0
18166
+ drawingShapes: markShapesStale(data.drawingShapes)
18126
18167
  };
18127
18168
  }
18128
18169
  function addSmartArtNodeAsChild(data, parentId, text) {
@@ -18150,7 +18191,7 @@ function addSmartArtNodeAsChild(data, parentId, text) {
18150
18191
  ...data,
18151
18192
  nodes,
18152
18193
  connections: connections.length > 0 ? connections : void 0,
18153
- drawingShapes: void 0
18194
+ drawingShapes: markShapesStale(data.drawingShapes)
18154
18195
  };
18155
18196
  }
18156
18197
  function reorderSmartArtNodeToIndex(data, nodeId, newIndex) {
@@ -18183,7 +18224,7 @@ function reorderSmartArtNodeToIndex(data, nodeId, newIndex) {
18183
18224
  return {
18184
18225
  ...data,
18185
18226
  nodes,
18186
- drawingShapes: void 0
18227
+ drawingShapes: markShapesStale(data.drawingShapes)
18187
18228
  };
18188
18229
  }
18189
18230
 
@@ -18223,9 +18264,61 @@ function setSmartArtNodeStyle(data, nodeId, style) {
18223
18264
  return {
18224
18265
  ...data,
18225
18266
  nodes,
18226
- drawingShapes: void 0
18267
+ drawingShapes: patchDrawingShapeStyle(data.drawingShapes, data.nodes, nodeId, style)
18227
18268
  };
18228
18269
  }
18270
+ function patchDrawingShapeStyle(shapes, nodes, nodeId, style) {
18271
+ if (!shapes || shapes.length === 0) {
18272
+ return shapes;
18273
+ }
18274
+ const idx = findShapeIndexForNode(shapes, nodes, nodeId);
18275
+ if (idx < 0) {
18276
+ return [];
18277
+ }
18278
+ const patch = {};
18279
+ if (style.fillColor !== void 0) {
18280
+ patch.fillColor = style.fillColor;
18281
+ }
18282
+ if (style.lineColor !== void 0) {
18283
+ patch.strokeColor = style.lineColor;
18284
+ }
18285
+ if (style.fontColor !== void 0) {
18286
+ patch.fontColor = style.fontColor;
18287
+ }
18288
+ if (Object.keys(patch).length === 0) {
18289
+ return shapes;
18290
+ }
18291
+ const updated = [...shapes];
18292
+ updated[idx] = { ...updated[idx], ...patch };
18293
+ return updated;
18294
+ }
18295
+ function findShapeIndexForNode(shapes, nodes, nodeId) {
18296
+ for (let i = 0; i < shapes.length; i++) {
18297
+ if (shapes[i].id.startsWith("reflow-") && shapes[i].id.endsWith(`-${nodeId}`)) {
18298
+ return i;
18299
+ }
18300
+ }
18301
+ if (shapes.length === nodes.length) {
18302
+ const nodeIdx = nodes.findIndex((n) => n.id === nodeId);
18303
+ if (nodeIdx >= 0) {
18304
+ return nodeIdx;
18305
+ }
18306
+ }
18307
+ const node = nodes.find((n) => n.id === nodeId);
18308
+ if (node?.text) {
18309
+ const text = node.text.trim();
18310
+ const matches = [];
18311
+ for (let i = 0; i < shapes.length; i++) {
18312
+ if (shapes[i].text?.trim() === text) {
18313
+ matches.push(i);
18314
+ }
18315
+ }
18316
+ if (matches.length === 1) {
18317
+ return matches[0];
18318
+ }
18319
+ }
18320
+ return -1;
18321
+ }
18229
18322
 
18230
18323
  // src/core/utils/smartart-editing-reflow-layouts-geometric.ts
18231
18324
  function reflowCycle(nodes, bounds) {
@@ -20282,20 +20375,24 @@ function switchSmartArtLayout(currentData, newLayoutType) {
20282
20375
  return {
20283
20376
  ...currentData,
20284
20377
  // Clear the raw layoutType string since the user is explicitly
20285
- // choosing a resolved category this avoids the heuristic
20378
+ // choosing a resolved category - this avoids the heuristic
20286
20379
  // re-resolve overriding their choice.
20287
20380
  layoutType: newLayoutType,
20288
20381
  resolvedLayoutType: newLayoutType,
20289
- // Clear the named layout preset switching category invalidates it
20382
+ // Clear the named layout preset - switching category invalidates it
20290
20383
  layout: void 0,
20291
- // Clear stale pre-computed drawing shapes from the old layout so the
20384
+ // Mark stale pre-computed drawing shapes from the old layout so the
20292
20385
  // 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
20386
+ // the new layout type. If the element never had drawing shapes (freshly
20387
+ // inserted), leave undefined so the family SVG renderer handles it
20388
+ // without triggering a lossy polygon-to-chevron reflow.
20389
+ drawingShapes: markShapesStale2(currentData.drawingShapes)
20296
20390
  // Preserve everything else: nodes, connections, colours, styles, chrome, etc.
20297
20391
  };
20298
20392
  }
20393
+ function markShapesStale2(shapes) {
20394
+ return shapes !== void 0 && shapes.length > 0 ? [] : void 0;
20395
+ }
20299
20396
  function isSwitchableLayoutType(layoutType) {
20300
20397
  return SWITCHABLE_LAYOUT_TYPES.includes(layoutType);
20301
20398
  }
@@ -37618,6 +37715,9 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37618
37715
  slideLayoutRelationshipType,
37619
37716
  relationshipsNamespace
37620
37717
  });
37718
+ for (const slide of slides) {
37719
+ await this.processSlideForSave(slide, saveSession, saveConstants);
37720
+ }
37621
37721
  const contentTypesXml2 = await this.zip.file("[Content_Types].xml")?.async("string");
37622
37722
  if (contentTypesXml2) {
37623
37723
  const contentTypesData = this.parser.parse(contentTypesXml2);
@@ -37629,9 +37729,6 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37629
37729
  });
37630
37730
  this.zip.file("[Content_Types].xml", this.builder.build(contentTypesData));
37631
37731
  }
37632
- for (const slide of slides) {
37633
- await this.processSlideForSave(slide, saveSession, saveConstants);
37634
- }
37635
37732
  for (const existingCommentPath of saveSession.getExistingCommentPaths()) {
37636
37733
  if (saveSession.isCommentPathActive(existingCommentPath)) {
37637
37734
  continue;
@@ -41506,7 +41603,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41506
41603
  for (const [, target] of layoutRels.entries()) {
41507
41604
  if (target.includes("slideMaster")) {
41508
41605
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41509
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41606
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41510
41607
  try {
41511
41608
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41512
41609
  if (masterXmlStr) {
@@ -41530,7 +41627,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41530
41627
  for (const [, target] of slideRels.entries()) {
41531
41628
  if (target.includes("slideLayout")) {
41532
41629
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41533
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41630
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41534
41631
  try {
41535
41632
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41536
41633
  if (layoutXmlStr) {
@@ -41558,7 +41655,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41558
41655
  for (const [, target] of slideRels.entries()) {
41559
41656
  if (target.includes("slideLayout")) {
41560
41657
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41561
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41658
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41562
41659
  try {
41563
41660
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41564
41661
  if (layoutXmlStr) {
@@ -41587,7 +41684,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41587
41684
  for (const [, target] of layoutRels.entries()) {
41588
41685
  if (target.includes("slideMaster")) {
41589
41686
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41590
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41687
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41591
41688
  try {
41592
41689
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41593
41690
  if (masterXmlStr) {
@@ -41616,7 +41713,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41616
41713
  for (const [, target] of slideRels.entries()) {
41617
41714
  if (target.includes("slideLayout")) {
41618
41715
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41619
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41716
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41620
41717
  try {
41621
41718
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41622
41719
  if (layoutXmlStr) {
@@ -41645,7 +41742,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41645
41742
  for (const [, target] of layoutRels.entries()) {
41646
41743
  if (target.includes("slideMaster")) {
41647
41744
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41648
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41745
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41649
41746
  try {
41650
41747
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41651
41748
  if (masterXmlStr) {
@@ -41670,7 +41767,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41670
41767
  for (const [, target] of slideRels.entries()) {
41671
41768
  if (target.includes("slideLayout")) {
41672
41769
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41673
- return target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41770
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41674
41771
  }
41675
41772
  }
41676
41773
  return void 0;
@@ -41686,7 +41783,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41686
41783
  for (const [, target] of layoutRels.entries()) {
41687
41784
  if (target.includes("slideMaster")) {
41688
41785
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41689
- return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41786
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41690
41787
  }
41691
41788
  }
41692
41789
  return void 0;
@@ -42330,7 +42427,7 @@ var PptxHandlerRuntime61 = class extends PptxHandlerRuntime60 {
42330
42427
  for (const [, target] of layoutRels.entries()) {
42331
42428
  if (target.includes("slideMaster")) {
42332
42429
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
42333
- masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
42430
+ masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
42334
42431
  break;
42335
42432
  }
42336
42433
  }
@@ -42464,7 +42561,7 @@ var PptxHandlerRuntime62 = class extends PptxHandlerRuntime61 {
42464
42561
  for (const [, target] of slideRels.entries()) {
42465
42562
  if (target.includes("slideLayout")) {
42466
42563
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
42467
- layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
42564
+ layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
42468
42565
  break;
42469
42566
  }
42470
42567
  }
@@ -46761,7 +46858,7 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
46761
46858
  for (const [, target] of layoutRels.entries()) {
46762
46859
  if (target.includes("slideMaster")) {
46763
46860
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
46764
- return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
46861
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
46765
46862
  }
46766
46863
  }
46767
46864
  return void 0;
@@ -46830,7 +46927,7 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
46830
46927
  for (const [, target] of masterRels.entries()) {
46831
46928
  if (target.includes("slideLayout")) {
46832
46929
  const masterDir = masterPath.substring(0, masterPath.lastIndexOf("/") + 1);
46833
- const resolved = target.startsWith("..") ? this.resolvePath(masterDir, target) : `ppt/${target.replace("../", "")}`;
46930
+ const resolved = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(masterDir, target) : `ppt/${target.replace("../", "")}`;
46834
46931
  masterLayoutPaths.add(resolved);
46835
46932
  }
46836
46933
  }
package/dist/index.mjs CHANGED
@@ -17947,6 +17947,9 @@ function resolveLayoutFromRawType(layoutType) {
17947
17947
  }
17948
17948
 
17949
17949
  // src/core/utils/smartart-editing-node-ops.ts
17950
+ function markShapesStale(shapes) {
17951
+ return shapes !== void 0 && shapes.length > 0 ? [] : void 0;
17952
+ }
17950
17953
  function nextModelId() {
17951
17954
  return `{${generateFontGuid()}}`;
17952
17955
  }
@@ -18000,8 +18003,7 @@ function addSmartArtNode(data, text, afterNodeId) {
18000
18003
  ...data,
18001
18004
  nodes,
18002
18005
  connections: connections.length > 0 ? connections : void 0,
18003
- // Clear pre-computed shapes to force layout reflow
18004
- drawingShapes: void 0
18006
+ drawingShapes: markShapesStale(data.drawingShapes)
18005
18007
  };
18006
18008
  }
18007
18009
  function removeSmartArtNode(data, nodeId) {
@@ -18030,7 +18032,7 @@ function removeSmartArtNode(data, nodeId) {
18030
18032
  ...data,
18031
18033
  nodes,
18032
18034
  connections: connections.length > 0 ? connections : void 0,
18033
- drawingShapes: void 0
18035
+ drawingShapes: markShapesStale(data.drawingShapes)
18034
18036
  };
18035
18037
  }
18036
18038
  function updateSmartArtNodeText(data, nodeId, newText) {
@@ -18038,9 +18040,48 @@ function updateSmartArtNodeText(data, nodeId, newText) {
18038
18040
  return {
18039
18041
  ...data,
18040
18042
  nodes,
18041
- drawingShapes: void 0
18043
+ drawingShapes: patchDrawingShapeText(data.drawingShapes, data.nodes, nodeId, newText)
18042
18044
  };
18043
18045
  }
18046
+ function patchDrawingShapeText(shapes, nodes, nodeId, newText) {
18047
+ if (!shapes || shapes.length === 0) {
18048
+ return shapes;
18049
+ }
18050
+ const idx = findDrawingShapeIndex(shapes, nodes, nodeId);
18051
+ if (idx < 0) {
18052
+ return [];
18053
+ }
18054
+ const updated = [...shapes];
18055
+ updated[idx] = { ...updated[idx], text: newText };
18056
+ return updated;
18057
+ }
18058
+ function findDrawingShapeIndex(shapes, nodes, nodeId) {
18059
+ for (let i = 0; i < shapes.length; i++) {
18060
+ if (shapes[i].id.startsWith("reflow-") && shapes[i].id.endsWith(`-${nodeId}`)) {
18061
+ return i;
18062
+ }
18063
+ }
18064
+ if (shapes.length === nodes.length) {
18065
+ const nodeIdx = nodes.findIndex((n) => n.id === nodeId);
18066
+ if (nodeIdx >= 0) {
18067
+ return nodeIdx;
18068
+ }
18069
+ }
18070
+ const node = nodes.find((n) => n.id === nodeId);
18071
+ if (node?.text) {
18072
+ const text = node.text.trim();
18073
+ const matches = [];
18074
+ for (let i = 0; i < shapes.length; i++) {
18075
+ if (shapes[i].text?.trim() === text) {
18076
+ matches.push(i);
18077
+ }
18078
+ }
18079
+ if (matches.length === 1) {
18080
+ return matches[0];
18081
+ }
18082
+ }
18083
+ return -1;
18084
+ }
18044
18085
  function reorderSmartArtNode(data, nodeId, direction) {
18045
18086
  const node = data.nodes.find((n) => n.id === nodeId);
18046
18087
  if (!node) {
@@ -18063,7 +18104,7 @@ function reorderSmartArtNode(data, nodeId, direction) {
18063
18104
  return {
18064
18105
  ...data,
18065
18106
  nodes,
18066
- drawingShapes: void 0
18107
+ drawingShapes: markShapesStale(data.drawingShapes)
18067
18108
  };
18068
18109
  }
18069
18110
  function promoteSmartArtNode(data, nodeId) {
@@ -18090,7 +18131,7 @@ function promoteSmartArtNode(data, nodeId) {
18090
18131
  ...data,
18091
18132
  nodes,
18092
18133
  connections: connections.length > 0 ? connections : void 0,
18093
- drawingShapes: void 0
18134
+ drawingShapes: markShapesStale(data.drawingShapes)
18094
18135
  };
18095
18136
  }
18096
18137
  function demoteSmartArtNode(data, nodeId) {
@@ -18117,7 +18158,7 @@ function demoteSmartArtNode(data, nodeId) {
18117
18158
  ...data,
18118
18159
  nodes,
18119
18160
  connections: connections.length > 0 ? connections : void 0,
18120
- drawingShapes: void 0
18161
+ drawingShapes: markShapesStale(data.drawingShapes)
18121
18162
  };
18122
18163
  }
18123
18164
  function addSmartArtNodeAsChild(data, parentId, text) {
@@ -18145,7 +18186,7 @@ function addSmartArtNodeAsChild(data, parentId, text) {
18145
18186
  ...data,
18146
18187
  nodes,
18147
18188
  connections: connections.length > 0 ? connections : void 0,
18148
- drawingShapes: void 0
18189
+ drawingShapes: markShapesStale(data.drawingShapes)
18149
18190
  };
18150
18191
  }
18151
18192
  function reorderSmartArtNodeToIndex(data, nodeId, newIndex) {
@@ -18178,7 +18219,7 @@ function reorderSmartArtNodeToIndex(data, nodeId, newIndex) {
18178
18219
  return {
18179
18220
  ...data,
18180
18221
  nodes,
18181
- drawingShapes: void 0
18222
+ drawingShapes: markShapesStale(data.drawingShapes)
18182
18223
  };
18183
18224
  }
18184
18225
 
@@ -18218,9 +18259,61 @@ function setSmartArtNodeStyle(data, nodeId, style) {
18218
18259
  return {
18219
18260
  ...data,
18220
18261
  nodes,
18221
- drawingShapes: void 0
18262
+ drawingShapes: patchDrawingShapeStyle(data.drawingShapes, data.nodes, nodeId, style)
18222
18263
  };
18223
18264
  }
18265
+ function patchDrawingShapeStyle(shapes, nodes, nodeId, style) {
18266
+ if (!shapes || shapes.length === 0) {
18267
+ return shapes;
18268
+ }
18269
+ const idx = findShapeIndexForNode(shapes, nodes, nodeId);
18270
+ if (idx < 0) {
18271
+ return [];
18272
+ }
18273
+ const patch = {};
18274
+ if (style.fillColor !== void 0) {
18275
+ patch.fillColor = style.fillColor;
18276
+ }
18277
+ if (style.lineColor !== void 0) {
18278
+ patch.strokeColor = style.lineColor;
18279
+ }
18280
+ if (style.fontColor !== void 0) {
18281
+ patch.fontColor = style.fontColor;
18282
+ }
18283
+ if (Object.keys(patch).length === 0) {
18284
+ return shapes;
18285
+ }
18286
+ const updated = [...shapes];
18287
+ updated[idx] = { ...updated[idx], ...patch };
18288
+ return updated;
18289
+ }
18290
+ function findShapeIndexForNode(shapes, nodes, nodeId) {
18291
+ for (let i = 0; i < shapes.length; i++) {
18292
+ if (shapes[i].id.startsWith("reflow-") && shapes[i].id.endsWith(`-${nodeId}`)) {
18293
+ return i;
18294
+ }
18295
+ }
18296
+ if (shapes.length === nodes.length) {
18297
+ const nodeIdx = nodes.findIndex((n) => n.id === nodeId);
18298
+ if (nodeIdx >= 0) {
18299
+ return nodeIdx;
18300
+ }
18301
+ }
18302
+ const node = nodes.find((n) => n.id === nodeId);
18303
+ if (node?.text) {
18304
+ const text = node.text.trim();
18305
+ const matches = [];
18306
+ for (let i = 0; i < shapes.length; i++) {
18307
+ if (shapes[i].text?.trim() === text) {
18308
+ matches.push(i);
18309
+ }
18310
+ }
18311
+ if (matches.length === 1) {
18312
+ return matches[0];
18313
+ }
18314
+ }
18315
+ return -1;
18316
+ }
18224
18317
 
18225
18318
  // src/core/utils/smartart-editing-reflow-layouts-geometric.ts
18226
18319
  function reflowCycle(nodes, bounds) {
@@ -20277,20 +20370,24 @@ function switchSmartArtLayout(currentData, newLayoutType) {
20277
20370
  return {
20278
20371
  ...currentData,
20279
20372
  // Clear the raw layoutType string since the user is explicitly
20280
- // choosing a resolved category this avoids the heuristic
20373
+ // choosing a resolved category - this avoids the heuristic
20281
20374
  // re-resolve overriding their choice.
20282
20375
  layoutType: newLayoutType,
20283
20376
  resolvedLayoutType: newLayoutType,
20284
- // Clear the named layout preset switching category invalidates it
20377
+ // Clear the named layout preset - switching category invalidates it
20285
20378
  layout: void 0,
20286
- // Clear stale pre-computed drawing shapes from the old layout so the
20379
+ // Mark stale pre-computed drawing shapes from the old layout so the
20287
20380
  // 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
20381
+ // the new layout type. If the element never had drawing shapes (freshly
20382
+ // inserted), leave undefined so the family SVG renderer handles it
20383
+ // without triggering a lossy polygon-to-chevron reflow.
20384
+ drawingShapes: markShapesStale2(currentData.drawingShapes)
20291
20385
  // Preserve everything else: nodes, connections, colours, styles, chrome, etc.
20292
20386
  };
20293
20387
  }
20388
+ function markShapesStale2(shapes) {
20389
+ return shapes !== void 0 && shapes.length > 0 ? [] : void 0;
20390
+ }
20294
20391
  function isSwitchableLayoutType(layoutType) {
20295
20392
  return SWITCHABLE_LAYOUT_TYPES.includes(layoutType);
20296
20393
  }
@@ -37613,6 +37710,9 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37613
37710
  slideLayoutRelationshipType,
37614
37711
  relationshipsNamespace
37615
37712
  });
37713
+ for (const slide of slides) {
37714
+ await this.processSlideForSave(slide, saveSession, saveConstants);
37715
+ }
37616
37716
  const contentTypesXml2 = await this.zip.file("[Content_Types].xml")?.async("string");
37617
37717
  if (contentTypesXml2) {
37618
37718
  const contentTypesData = this.parser.parse(contentTypesXml2);
@@ -37624,9 +37724,6 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37624
37724
  });
37625
37725
  this.zip.file("[Content_Types].xml", this.builder.build(contentTypesData));
37626
37726
  }
37627
- for (const slide of slides) {
37628
- await this.processSlideForSave(slide, saveSession, saveConstants);
37629
- }
37630
37727
  for (const existingCommentPath of saveSession.getExistingCommentPaths()) {
37631
37728
  if (saveSession.isCommentPathActive(existingCommentPath)) {
37632
37729
  continue;
@@ -41501,7 +41598,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41501
41598
  for (const [, target] of layoutRels.entries()) {
41502
41599
  if (target.includes("slideMaster")) {
41503
41600
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41504
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41601
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41505
41602
  try {
41506
41603
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41507
41604
  if (masterXmlStr) {
@@ -41525,7 +41622,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41525
41622
  for (const [, target] of slideRels.entries()) {
41526
41623
  if (target.includes("slideLayout")) {
41527
41624
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41528
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41625
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41529
41626
  try {
41530
41627
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41531
41628
  if (layoutXmlStr) {
@@ -41553,7 +41650,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41553
41650
  for (const [, target] of slideRels.entries()) {
41554
41651
  if (target.includes("slideLayout")) {
41555
41652
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41556
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41653
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41557
41654
  try {
41558
41655
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41559
41656
  if (layoutXmlStr) {
@@ -41582,7 +41679,7 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
41582
41679
  for (const [, target] of layoutRels.entries()) {
41583
41680
  if (target.includes("slideMaster")) {
41584
41681
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41585
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41682
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41586
41683
  try {
41587
41684
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41588
41685
  if (masterXmlStr) {
@@ -41611,7 +41708,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41611
41708
  for (const [, target] of slideRels.entries()) {
41612
41709
  if (target.includes("slideLayout")) {
41613
41710
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41614
- const layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41711
+ const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41615
41712
  try {
41616
41713
  const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
41617
41714
  if (layoutXmlStr) {
@@ -41640,7 +41737,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41640
41737
  for (const [, target] of layoutRels.entries()) {
41641
41738
  if (target.includes("slideMaster")) {
41642
41739
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41643
- const masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41740
+ const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41644
41741
  try {
41645
41742
  const masterXmlStr = await this.zip.file(masterPath)?.async("string");
41646
41743
  if (masterXmlStr) {
@@ -41665,7 +41762,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41665
41762
  for (const [, target] of slideRels.entries()) {
41666
41763
  if (target.includes("slideLayout")) {
41667
41764
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
41668
- return target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41765
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
41669
41766
  }
41670
41767
  }
41671
41768
  return void 0;
@@ -41681,7 +41778,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
41681
41778
  for (const [, target] of layoutRels.entries()) {
41682
41779
  if (target.includes("slideMaster")) {
41683
41780
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
41684
- return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41781
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
41685
41782
  }
41686
41783
  }
41687
41784
  return void 0;
@@ -42325,7 +42422,7 @@ var PptxHandlerRuntime61 = class extends PptxHandlerRuntime60 {
42325
42422
  for (const [, target] of layoutRels.entries()) {
42326
42423
  if (target.includes("slideMaster")) {
42327
42424
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
42328
- masterPath = target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
42425
+ masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
42329
42426
  break;
42330
42427
  }
42331
42428
  }
@@ -42459,7 +42556,7 @@ var PptxHandlerRuntime62 = class extends PptxHandlerRuntime61 {
42459
42556
  for (const [, target] of slideRels.entries()) {
42460
42557
  if (target.includes("slideLayout")) {
42461
42558
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
42462
- layoutPath = target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
42559
+ layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
42463
42560
  break;
42464
42561
  }
42465
42562
  }
@@ -46756,7 +46853,7 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
46756
46853
  for (const [, target] of layoutRels.entries()) {
46757
46854
  if (target.includes("slideMaster")) {
46758
46855
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
46759
- return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
46856
+ return target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
46760
46857
  }
46761
46858
  }
46762
46859
  return void 0;
@@ -46825,7 +46922,7 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
46825
46922
  for (const [, target] of masterRels.entries()) {
46826
46923
  if (target.includes("slideLayout")) {
46827
46924
  const masterDir = masterPath.substring(0, masterPath.lastIndexOf("/") + 1);
46828
- const resolved = target.startsWith("..") ? this.resolvePath(masterDir, target) : `ppt/${target.replace("../", "")}`;
46925
+ const resolved = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(masterDir, target) : `ppt/${target.replace("../", "")}`;
46829
46926
  masterLayoutPaths.add(resolved);
46830
46927
  }
46831
46928
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-viewer-core",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "PowerPoint PPTX engine: parse, edit, serialize, and convert .pptx files. Framework-agnostic TypeScript SDK.",
5
5
  "keywords": [
6
6
  "angular",