node-pptx-templater 1.1.3 → 1.1.6

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
@@ -5,22 +5,6 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.1.3] - 2026-06-22
9
-
10
- ### Fixed
11
-
12
- - **Layout Preservation in `addCellShape()`**: Fixed a critical layout bug where querying cell bounds or adding cell shapes dynamically (via `addCellShape()` or `updateCellShape()`) mutated table row heights inside the XML. The sizing/positioning logic now runs in a layout-only mode, keeping the table XML completely untouched and respecting original template custom row heights.
13
-
14
- ## [1.1.2] - 2026-06-22
15
-
16
- ### Fixed
17
-
18
- - **Slide Link Relationships Target Paths**: Fixed PowerPoint "Repair Mode" errors when adding slide-to-slide hyperlinks (via `addSlideLink` or `addImageLink`). The relative target path resolves correctly to the sibling filename `slideX.xml` instead of using the redundant parent prefix `../slides/slideX.xml` (which exited and re-entered the same directory, violating PowerPoint's relative path resolution rules).
19
-
20
- ### Added
21
-
22
- - **Redundant Traversal Validation**: Added automated check in `ValidationEngine` to identify and error on redundant relative path traversals inside relationship files (e.g. referencing `../slides/slideX.xml` from a source slide file already located in `ppt/slides/`).
23
-
24
8
  ## [1.1.0] - 2026-06-12
25
9
 
26
10
  ### Added
package/README.md CHANGED
@@ -172,51 +172,27 @@ const meta = await ppt.getTableRows('SalesTable', { includeMetadata: true });
172
172
  ```
173
173
 
174
174
  ### Table Cell Shapes
175
- Cell shapes are overlay graphics anchored within table cells. They are positioned absolutely based on cell bounds, and **never** modify row heights, column widths, cell margins, or trigger table reflow.
176
-
177
- #### Merged Cell Support
178
- When targeting a merged cell (spanned using `rowSpan` or `colSpan`), `addCellShape()` dynamically resolves the **actual rendered bounds** of the entire merged cell region (summing the width and height of the spanned rows/columns). The shape is positioned and aligned relative to this final merged boundary. Any offset `x` and `y` specified is interpreted relative to the top-left corner of the resolved merged cell region.
179
-
180
- #### Alignment & Presets
181
- Shapes can be aligned dynamically within the cell (or merged region) using preset positions or explicit alignments:
182
- * **Presets**: Use `position` values like `'top-left'`, `'center'`, `'bottom-right'`, etc.
183
- * **Alignment Options**: Set `alignX: 'left' | 'center' | 'right'` and `alignY: 'top' | 'middle' | 'bottom'`. If no alignments or offsets are provided, shapes default to true centering (`'center'`/`'middle'`).
184
- * **Offsets & Padding**: Offsets (`x`, `y`) are applied relative to the resolved alignment. For instance, when `alignX: 'right'` is used, the shape is placed at `cellRight - shapeWidth - x` (defaulting to a `5px` padding if `x` is omitted).
175
+ Cell shapes are overlay graphics anchored within table cells. They are positioned absolutely based on cell bounds, and **never** modify row heights, column widths, cell margins, or trigger table reflow. Offsets (`x`, `y`) are relative to the cell's top-left corner. Oversized shapes are scaled down proportionally to fit inside the cell.
185
176
 
186
177
  ```javascript
187
- // Add a status icon centered in a merged cell (rowSpan=2, colSpan=2)
188
- await ppt.addCellShape('StatusTable', 1, 1, {
178
+ // Add a simple indicator
179
+ await ppt.addCellShape('SalesTable', 2, 1, {
189
180
  type: 'circle',
190
181
  width: 12,
191
182
  height: 12,
192
- fill: '#10B981', // Green status dot
193
- alignX: 'center',
194
- alignY: 'middle' // Visually centered in the merged cell
183
+ fill: '#10B981' // Green status dot
195
184
  });
196
185
 
197
- // Add a badge with text and explicit offsets inside a merged cell
198
- await ppt.addCellShape('StatusTable', 1, 1, {
186
+ // Add a badge with text and custom offsets
187
+ await ppt.addCellShape('SalesTable', 1, 2, {
199
188
  type: 'badge',
200
- text: 'Urgent',
201
- fill: '#EF4444',
202
- alignX: 'left',
203
- alignY: 'top',
204
- x: 5,
205
- y: 3,
189
+ text: 'Active',
190
+ fill: '#3B82F6',
191
+ x: 4,
192
+ y: 2,
206
193
  width: 50,
207
194
  height: 16
208
195
  });
209
-
210
- // Add an indicator with bottom-right alignment and custom padding
211
- await ppt.addCellShape('StatusTable', 1, 1, {
212
- type: 'icon',
213
- icon: 'up',
214
- size: 14,
215
- alignX: 'right',
216
- alignY: 'bottom',
217
- x: 4,
218
- y: 2
219
- });
220
196
  ```
221
197
 
222
198
  ### XML Folder Workflow
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-pptx-templater",
3
- "version": "1.1.3",
3
+ "version": "1.1.6",
4
4
  "description": "High-performance, low-level PowerPoint (PPTX) OpenXML template engine for Node.js. Dynamically replace text, insert images, update charts (with Excel workbook data caching), and merge table cells without PowerPoint corruption or Repair Mode prompts.",
5
5
  "main": "./src/index.js",
6
6
  "type": "commonjs",
@@ -37,7 +37,6 @@
37
37
  "example:table-extraction": "node examples/table-extraction.js",
38
38
  "example:nested-rows": "node examples/nested-table-rows.js",
39
39
  "example:xml-folder": "node examples/xml-folder-workflow.js",
40
- "example:all": "node scripts/run-examples-check.js",
41
40
  "prepublishOnly": "npm run lint && npm run test"
42
41
  },
43
42
  "keywords": [
@@ -473,10 +473,14 @@ class PPTXTemplater {
473
473
  throw new PPTXError(`Destination is a file: ${outputPath}`)
474
474
  }
475
475
  const files = fs.readdirSync(resolvedOut)
476
- if (files.length > 0 && !options.overwrite) {
477
- throw new PPTXError(
478
- `Destination directory "${outputPath}" is not empty. Set overwrite: true to overwrite.`
479
- )
476
+ if (files.length > 0) {
477
+ if (!options.overwrite) {
478
+ throw new PPTXError(
479
+ `Destination directory "${outputPath}" is not empty. Set overwrite: true to overwrite.`
480
+ )
481
+ } else {
482
+ await fs.emptyDir(resolvedOut)
483
+ }
480
484
  }
481
485
  } else {
482
486
  await fs.ensureDir(resolvedOut)
@@ -1591,7 +1595,14 @@ class PPTXTemplater {
1591
1595
  this.#assertLoaded()
1592
1596
  const targetIndices = this.#getTargetSlideIndices()
1593
1597
  for (const idx of targetIndices) {
1594
- this.#tableManager.addTableRow(idx, tableId, rowData, this.#slideManager, options)
1598
+ this.#tableManager.addTableRow(
1599
+ idx,
1600
+ tableId,
1601
+ rowData,
1602
+ this.#slideManager,
1603
+ this.#shapeManager,
1604
+ options
1605
+ )
1595
1606
  }
1596
1607
  return this
1597
1608
  }
@@ -1610,7 +1621,13 @@ class PPTXTemplater {
1610
1621
  this.#assertLoaded()
1611
1622
  const targetIndices = this.#getTargetSlideIndices()
1612
1623
  for (const idx of targetIndices) {
1613
- this.#tableManager.removeTableRow(idx, tableId, rowIndex, this.#slideManager)
1624
+ this.#tableManager.removeTableRow(
1625
+ idx,
1626
+ tableId,
1627
+ rowIndex,
1628
+ this.#slideManager,
1629
+ this.#shapeManager
1630
+ )
1614
1631
  }
1615
1632
  return this
1616
1633
  }
@@ -1630,7 +1647,14 @@ class PPTXTemplater {
1630
1647
  this.#assertLoaded()
1631
1648
  const targetIndices = this.#getTargetSlideIndices()
1632
1649
  for (const idx of targetIndices) {
1633
- this.#tableManager.insertTableRow(idx, tableId, rowIndex, rowData, this.#slideManager)
1650
+ this.#tableManager.insertTableRow(
1651
+ idx,
1652
+ tableId,
1653
+ rowIndex,
1654
+ rowData,
1655
+ this.#slideManager,
1656
+ this.#shapeManager
1657
+ )
1634
1658
  }
1635
1659
  return this
1636
1660
  }
@@ -1655,7 +1679,8 @@ class PPTXTemplater {
1655
1679
  tableId,
1656
1680
  sourceRowIndex,
1657
1681
  targetRowIndex,
1658
- this.#slideManager
1682
+ this.#slideManager,
1683
+ this.#shapeManager
1659
1684
  )
1660
1685
  }
1661
1686
  return this
@@ -1735,7 +1760,16 @@ class PPTXTemplater {
1735
1760
  }
1736
1761
 
1737
1762
  for (const idx of targetIndices) {
1738
- this.#tableManager.mergeCells(idx, tableId, sRow, sCol, eRow, eCol, this.#slideManager)
1763
+ this.#tableManager.mergeCells(
1764
+ idx,
1765
+ tableId,
1766
+ sRow,
1767
+ sCol,
1768
+ eRow,
1769
+ eCol,
1770
+ this.#slideManager,
1771
+ this.#shapeManager
1772
+ )
1739
1773
  }
1740
1774
  return this
1741
1775
  }
@@ -1786,9 +1820,25 @@ class PPTXTemplater {
1786
1820
 
1787
1821
  for (const idx of targetIndices) {
1788
1822
  if (isCellCoord) {
1789
- this.#tableManager.unmergeCells(idx, tableId, cellRow, cellCol, this.#slideManager)
1823
+ this.#tableManager.unmergeCells(
1824
+ idx,
1825
+ tableId,
1826
+ cellRow,
1827
+ cellCol,
1828
+ this.#slideManager,
1829
+ this.#shapeManager
1830
+ )
1790
1831
  } else {
1791
- this.#tableManager.unmergeCells(idx, tableId, sRow, sCol, eRow, eCol, this.#slideManager)
1832
+ this.#tableManager.unmergeCells(
1833
+ idx,
1834
+ tableId,
1835
+ sRow,
1836
+ sCol,
1837
+ eRow,
1838
+ eCol,
1839
+ this.#slideManager,
1840
+ this.#shapeManager
1841
+ )
1792
1842
  }
1793
1843
  }
1794
1844
  return this