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 +0 -16
- package/README.md +10 -34
- package/package.json +1 -2
- package/src/core/PPTXTemplater.js +61 -11
- package/src/managers/ShapeManager.js +296 -85
- package/src/managers/TableManager.js +700 -88
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
|
|
188
|
-
await ppt.addCellShape('
|
|
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'
|
|
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
|
|
198
|
-
await ppt.addCellShape('
|
|
186
|
+
// Add a badge with text and custom offsets
|
|
187
|
+
await ppt.addCellShape('SalesTable', 1, 2, {
|
|
199
188
|
type: 'badge',
|
|
200
|
-
text: '
|
|
201
|
-
fill: '#
|
|
202
|
-
|
|
203
|
-
|
|
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
|
+
"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
|
|
477
|
-
|
|
478
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|