node-pptx-templater 1.0.3 → 1.0.4

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +28 -3
  2. package/README.md +136 -343
  3. package/package.json +12 -3
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ 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.0.3] - 2026-06-02
9
+
10
+ ### Added
11
+ - **Dynamic Formatting in updateTable**: Added support for inline cell styling (color fill `fill`, text alignment `align`, and `fontSize`) directly on cell objects passed to `updateTable`.
12
+ - **Comprehensive Tailwind Site**: Overhauled doc builder script to generate a premium Tailwind CSS documentation portal with clientside search, clipboard copying, sitemap.xml, robots.txt, and Schema.org metadata.
13
+
14
+ ### Fixed
15
+ - **XML Element Ordering**: Enforced strict schema-valid element sequence (`a:pPr` -> runs -> `a:endParaRPr`) in slide table cell paragraphs. This resolves the bug where split cells inheriting from template merged cells had their text runs ignored by PowerPoint's XML compiler.
16
+ - **Template Style Inheritance**: Fixed a bug in `updateTable` where cloned rows always copied the first data row (`trs[1]`). The engine now correctly inherits formatting, alignment, and fill styles from matching indices in the template (`trs[i]`) when available.
17
+
18
+ ## [1.0.2] - 2026-06-02
19
+
20
+ ### Added
21
+ - **Table Cell Merging & Unmerging Engine**: Fully implemented horizontal cell spans (`gridSpan`, `hMerge`), vertical cell spans (`rowSpan`, `vMerge`), and rectangular block merges.
22
+ - **PowerPoint Repair Protection**: Implemented unique 32-bit unsigned `rowId` generation inside `<a16:rowId>` XML tags for all cloned and inserted rows, eliminating PowerPoint's "Repair Mode" error prompts.
23
+ - **Merge Integrations**: Integrated template-driven merges (`merge` configs array and cell-level `colSpan`/`rowSpan`) inside the main `updateTable` orchestrator.
24
+ - **Integration Test Suite**: Added a comprehensive merge test script under `tests/integration/PPTXMerge.test.js`.
25
+
26
+ ## [1.0.1] - 2026-05-19
27
+
28
+ ### Changed
29
+ - **CommonJS Target Conversion**: Converted the source code modules compilation and packaging layout from pure ES Modules (ESM) to CommonJS (CJS) to ensure compatibility with standard Node.js deployment, packaging, and edge runtime environments.
30
+
8
31
  ## [1.0.0] - 2026-05-17
9
32
 
10
33
  ### Added
@@ -16,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
39
  - `ChartManager` — direct chart XML data updates (bar, line, pie, area, scatter)
17
40
  - `TableManager` — table row replacement preserving all formatting
18
41
  - `HyperlinkManager` — external URL and slide-to-slide hyperlink injection
19
- - `MediaManager` — image embedding with SHA-1 content deduplication
42
+ - `MediaManager` — image embedding with SHA-1 deduplication
20
43
  - `TemplateEngine` — `{{placeholder}}` replacement with fragmented run normalization
21
44
  - `OutputWriter` — file, buffer, and stream output
22
45
  - CLI: `build`, `validate`, `inspect`, `extract`, `debug` commands
@@ -29,11 +52,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
29
52
  - MIT License
30
53
 
31
54
  ### Architecture
32
- - Pure JavaScript ES Modules (no TypeScript)
33
55
  - Zero PPTX generation library dependencies
34
56
  - Only uses: `jszip`, `fast-xml-parser`, `fs-extra`, `commander`, `chalk`, `ora`
35
57
  - Async/await throughout
36
58
  - Private class fields (`#field`) for encapsulation
37
59
  - Modular architecture following SOLID principles
38
60
 
39
- [1.0.0]: https://github.com/jsuyog2/pptx-templater/releases/tag/v1.0.0
61
+ [1.0.3]: https://github.com/jsuyog2/node-pptx-templater/compare/v1.0.2...v1.0.3
62
+ [1.0.2]: https://github.com/jsuyog2/node-pptx-templater/compare/v1.0.1...v1.0.2
63
+ [1.0.1]: https://github.com/jsuyog2/node-pptx-templater/compare/v1.0.0...v1.0.1
64
+ [1.0.0]: https://github.com/jsuyog2/node-pptx-templater/releases/tag/v1.0.0
package/README.md CHANGED
@@ -1,24 +1,38 @@
1
1
  # node-pptx-templater
2
2
 
3
- > A low-level PowerPoint OpenXML templating engine for Node.js that generates and edits PPTX files directly through XML manipulation without relying on PowerPoint generation libraries.
3
+ > 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.
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/node-pptx-templater.svg)](https://www.npmjs.com/package/node-pptx-templater)
6
- [![CI](https://github.com/jsuyog2/node-pptx-templater/actions/workflows/ci.yml/badge.svg)](https://github.com/jsuyog2/node-pptx-templater/actions/workflows/ci.yml)
7
- [![Coverage](https://img.shields.io/codecov/c/github/jsuyog2/node-pptx-templater)](https://codecov.io/gh/jsuyog2/node-pptx-templater)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
9
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org)
5
+ [![npm version](https://img.shields.io/npm/v/node-pptx-templater.svg?style=flat-square&color=blue)](https://www.npmjs.com/package/node-pptx-templater)
6
+ [![CI Build Status](https://img.shields.io/github/actions/workflow/status/jsuyog2/node-pptx-templater/ci.yml?branch=main&style=flat-square)](https://github.com/jsuyog2/node-pptx-templater/actions/workflows/ci.yml)
7
+ [![Bundle Size](https://img.shields.io/bundlephobia/min/node-pptx-templater?style=flat-square&color=brightgreen)](https://bundlephobia.com/package/node-pptx-templater)
8
+ [![Downloads](https://img.shields.io/npm/dm/node-pptx-templater.svg?style=flat-square&color=orange)](https://www.npmjs.com/package/node-pptx-templater)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg?style=flat-square)](./LICENSE)
10
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen?style=flat-square)](https://nodejs.org)
11
+
12
+ ---
13
+
14
+ ## ⚡ Why node-pptx-templater?
15
+
16
+ Traditional PowerPoint generation libraries require building slides from scratch in code, which is verbose, hard to maintain, and strips away the power of visual design tools.
17
+
18
+ `node-pptx-templater` takes a different approach: **Design visually in PowerPoint, populate dynamically in Node.js.**
19
+
20
+ You create slide decks using PowerPoint, Google Slides, or Keynote, set your formatting, themes, animations, and layouts, and place placeholders like `{{company}}` or `{{revenue-chart}}`. `node-pptx-templater` parses the template and updates text, injects images, replaces chart values (updating both Excel workbook data caches and XML shapes), and merges tables dynamically while keeping the presentation 100% compliant with standard OpenXML guidelines.
10
21
 
11
22
  ---
12
23
 
13
24
  ## ✨ Features
14
25
 
15
- - 🏗️ **Zero PPTX Library Dependencies**: Operates entirely via low-level XML/ZIP manipulation.
16
- - 🔁 **Advanced Text Replacement**: Handles fragmented runs seamlessly (`{{placeholders}}`).
17
- - 📊 **Comprehensive Chart Support**: Bar, Column, Line, Pie, Doughnut, Area, Scatter—preserves original themes.
18
- - 📋 **Safe Table Updates**: Fully manages row insertion, deletion, merging, resizing, and cell formatting while maintaining PowerPoint integrity (prevents repair warnings by generating unique row IDs).
19
- - 🎨 **Shape & Image Manipulation**: Update text, clone, position, replace, or delete slide components.
20
- - 🎯 **Slide Operations**: Duplicate, reorder, insert, or delete slide parts on the fly.
21
- - 🔍 **Deep Integrity Validation**: Live validation of relationships, XML schema consistency, table columns, and duplicates prior to saving.
26
+ - 🏗️ **Zero Native Office/Java Dependencies**: Runs on pure Javascript/Node.js, making it ideal for high-throughput cloud environments, Lambda, or serverless runtimes.
27
+ - 🔁 **Fragmented Placeholder Resolution**: PowerPoint often splits text runs like `{{company}}` into `<a:r>` nodes. Our engine merges and resolves fragmented tags automatically.
28
+ - 📊 **Full Chart Engine Integration**: Supports Bar, Column, Line, Pie, Doughnut, Area, Scatter, and Bubble charts. Automatically synchronizes chart XML properties and coordinates with the embedded Excel sheets (`ppt/embeddings/`).
29
+ - 📋 **Flexible Table Merging & Templating**:
30
+ - Horizontal column merge (`gridSpan` & `hMerge`), vertical row merge (`rowSpan` & `vMerge`), and rectangular block merges.
31
+ - Formats cells dynamically with inline options (`align`, `fontSize`, `fill`).
32
+ - Automatically handles slide table duplicates by generating unique `<a16:rowId>` 32-bit hashes to **prevent PowerPoint Repair Mode** screens.
33
+ - 🎨 **Shape & Image Manipulation**: Find shapes, clone layout blocks with offsets, replace image sources while keeping exact positions, or delete elements.
34
+ - 🎯 **Slide Management Operations**: Duplicate, reorder, delete, and import slides from external templates with automatic media asset deduplication.
35
+ - 🔍 **Deep Packaging Integrity Validation**: Real-time checking of relationships, XML schemas, table column numbers, and override duplicates.
22
36
 
23
37
  ---
24
38
 
@@ -32,58 +46,92 @@ npm install node-pptx-templater
32
46
 
33
47
  ## 🚀 Quick Start
34
48
 
49
+ Get up and running in under 60 seconds with this simple template rendering example:
50
+
35
51
  ```js
36
52
  const { PPTXTemplater } = require('node-pptx-templater');
37
53
 
38
- async function run() {
39
- // Load presentation template
40
- const ppt = await PPTXTemplater.load('template.pptx');
54
+ async function main() {
55
+ // 1. Load your PowerPoint presentation template
56
+ const ppt = await PPTXTemplater.load('monthly_report_template.pptx');
41
57
 
42
- // Use Slide 1 and replace text placeholders
58
+ // 2. Select slide 1 and execute operations
43
59
  ppt.useSlide(1)
44
- .replaceTextByTag('title', 'Annual Sales Report')
45
- .replaceMultiple({ company: 'Google DeepMind', year: '2026' });
60
+ .replaceTextByTag('title', 'Quarterly Earnings Report')
61
+ .replaceMultiple({
62
+ company: 'Acme Corporation',
63
+ year: '2026'
64
+ });
46
65
 
47
- // Update chart data on Slide 2
66
+ // 3. Update chart series data on Slide 2
48
67
  ppt.useSlide(2)
49
68
  .updateChartData('sales-chart', {
50
69
  categories: ['Q1', 'Q2', 'Q3', 'Q4'],
51
- series: [{ name: 'Revenue', values: [100, 150, 180, 220] }]
70
+ series: [
71
+ { name: 'Target', values: [100, 120, 140, 160] },
72
+ { name: 'Revenue', values: [105, 118, 145, 172] }
73
+ ]
52
74
  });
53
75
 
54
- // Save the result (validates structural integrity automatically)
55
- await ppt.saveToFile('output.pptx');
76
+ // 4. Update table with cell merging and formatting on Slide 3
77
+ ppt.useSlide(3)
78
+ .updateTable('sales-table', [
79
+ ['Region', 'Q1 Actual', 'Q2 Actual', 'Status'],
80
+ ['North', '120k', '140k', { value: 'On Track', align: 'ctr', fill: '10b981' }],
81
+ ['South', '95k', '110k', { value: 'Review', align: 'ctr', fill: 'f59e0b' }]
82
+ ]);
83
+
84
+ // 5. Save the non-corrupted PPTX back to disk
85
+ await ppt.saveToFile('./output/annual_earnings.pptx');
56
86
  }
57
- run();
87
+
88
+ main().catch(err => console.error(err));
58
89
  ```
59
90
 
60
91
  ---
61
92
 
62
- ## 🏗️ Architecture & OpenXML Internals
93
+ ## 🏗️ OpenXML Architecture & Internals
63
94
 
64
- A PPTX file is an OPC (Open Packaging Convention) ZIP containing XML parts:
95
+ A `.pptx` file is an OPC (Open Packaging Convention) ZIP archive containing structured XML documents and asset folders:
65
96
 
66
- - `/ppt/presentation.xml` – The slides inventory (`sldIdLst`) and masters.
67
- - `/ppt/slides/slideN.xml` – Slide elements (shapes, images, tables).
68
- - `/ppt/slides/_rels/slideN.xml.rels` – Relationship links (`rId`).
69
- - `[Content_Types].xml` – Declares MIME types for slide parts, charts, and media.
97
+ - `[Content_Types].xml` – Global manifest declaring content MIME types for every file part in the ZIP.
98
+ - `_rels/.rels`Root-level package relationship index.
99
+ - `ppt/presentation.xml` – Root presentation settings and slide inventory (`sldIdLst`).
100
+ - `ppt/slides/slideN.xml` – Main slide canvas storing shapes, lines, tables, text runs, and layout components.
101
+ - `ppt/slides/_rels/slideN.xml.rels` – Relationship indexes mapping slide XML components to charts, layouts, and image assets.
70
102
 
71
- ### The rowId Table Corruption Bug
72
- Microsoft PowerPoint assigns an `<a16:rowId>` identifier to each row to facilitate collaborative editing. Duplicate row IDs trigger the PowerPoint **Repair Mode**, causing slide elements and styles to break.
73
- `node-pptx-templater` generates unique 32-bit unsigned integers for `<a16:rowId>` whenever a table row is cloned, appended, or inserted, ensuring output documents open flawlessly in MS PowerPoint, Google Slides, and LibreOffice.
103
+ ### Preventing PowerPoint Table Repair Errors
104
+ PowerPoint slide tables utilize unique 32-bit identifiers inside `<a16:rowId>` nodes for collaborative edits. Duplicating rows using naive array copy operations results in overlapping IDs, triggering Microsoft PowerPoint's **"PowerPoint found a problem with content"** repair screen on open.
105
+ `node-pptx-templater` intercepts all table operations (adding, cloning, inserting, or merging rows) and dynamically injects newly generated unique `rowId` hashes, ensuring a seamless, warning-free loading experience in:
106
+ - Microsoft PowerPoint (Desktop, Mac, Online)
107
+ - Google Slides
108
+ - LibreOffice Impress
74
109
 
75
110
  ---
76
111
 
77
- ## 📚 API Reference
112
+ ## 📊 Feature Comparison Matrix
78
113
 
79
- Here is the complete reference of all public APIs.
114
+ | Feature / Library | `node-pptx-templater` | `pptxgenjs` | `pptx-template` | `pptx-automizer` | `officegen` |
115
+ |:---|:---:|:---:|:---:|:---:|:---:|
116
+ | **Approach** | **Template-based** | Code-based | Template-based | Template-based | Code-based |
117
+ | **No PPTX Corruption / Repair Warnings** | **Yes** (Automatic Metadata Sync) | Yes | No (Fragile row duplication) | Yes | Yes (Limited layouts) |
118
+ | **Text Run Fragmentation Resolution** | **Yes** (Dynamic merging) | N/A | No (Placeholder breaks) | Yes | N/A |
119
+ | **Chart Data Workbook Sync** | **Yes** (Direct excel caching) | Yes | No (Only raw XML text) | Yes | Yes |
120
+ | **Horizontal & Vertical Cell Merge** | **Yes** (gridSpan, rowSpan, hMerge, vMerge) | Yes | No | No | No |
121
+ | **Slide Duplication & Reordering** | **Yes** | No | No | Yes | No |
122
+ | **External Slide Imports** | **Yes** (With asset deduplication) | No | No | Yes | No |
123
+ | **Dependencies** | **Zero Native Dependencies** | Zero | Zero | Zero | Node-zip, xmlbuilder |
80
124
 
81
- ### Slide Features
125
+ ---
126
+
127
+ ## 📚 API Reference
128
+
129
+ ### Slide Operations
82
130
 
83
131
  #### `duplicateSlide(slideIndex, atPosition)`
84
132
  Duplicates a slide.
85
133
  ```js
86
- ppt.duplicateSlide(1, 2); // Duplicate Slide 1 and insert it as Slide 2
134
+ ppt.duplicateSlide(1, 2); // Duplicate Slide 1 and insert it at position 2
87
135
  ```
88
136
 
89
137
  #### `deleteSlide(slideIndex)`
@@ -98,363 +146,108 @@ Moves a slide to a new position.
98
146
  ppt.moveSlide(1, 3); // Move Slide 1 to position 3
99
147
  ```
100
148
 
101
- #### `insertSlide(slideIndex, options)`
102
- Inserts a new blank slide at a specific position.
103
- ```js
104
- ppt.insertSlide(2, { title: 'New Layout Slide' });
105
- ```
106
-
107
- #### `getSlides()`
108
- Returns metadata about all slides in the deck.
149
+ #### `importSlideFrom(sourcePresentation, sourceSlideIndex)`
150
+ Deep-copies a slide from another loaded presentation, automatically remapping layouts, shapes, charts, and deduplicating media assets.
109
151
  ```js
110
- const slides = ppt.getSlides();
111
- console.log(slides);
152
+ const source = await PPTXTemplater.load('marketing_slides.pptx');
153
+ await ppt.importSlideFrom(source, 2); // Import Slide 2 of marketing deck
112
154
  ```
113
155
 
114
156
  ---
115
157
 
116
- ### Table Features
158
+ ### Table Manipulation
117
159
 
118
- #### `addTableRow(tableId, rowData)`
119
- Appends a new row to the table.
160
+ #### `updateTable(tableId, data)`
161
+ Updates a table with rows data, merge rules, and cell styles.
120
162
  ```js
121
- ppt.addTableRow('sales-table', ['Q4', '150', '210', '190', '250']);
163
+ ppt.updateTable('revenue-table', [
164
+ ['Year', 'Revenue', 'Profit'],
165
+ ['2025', '120k', '40k'],
166
+ ['2026', '150k', { value: '60k', fill: '10b981', align: 'ctr' }]
167
+ ]);
122
168
  ```
123
169
 
124
- #### `removeTableRow(tableId, rowIndex)`
125
- Removes a table row.
170
+ #### `mergeCells(options)`
171
+ Merges a rectangular block of cells. Supports horizontal, vertical, and block merging, concatenating all text from the merged region into the top-left cell.
126
172
  ```js
127
- ppt.removeTableRow('sales-table', 1); // Delete 2nd row (0-based)
128
- ```
129
-
130
- #### `insertTableRow(tableId, rowIndex, rowData)`
131
- Inserts a row at a specific index.
132
- ```js
133
- ppt.insertTableRow('sales-table', 2, ['Q3', '100', '120', '140', '160']);
134
- ```
135
-
136
- #### `cloneTableRow(tableId, sourceRowIndex, targetRowIndex)`
137
- Clones a row style/data and inserts it.
138
- ```js
139
- ppt.cloneTableRow('sales-table', 1, 3);
140
- ```
141
-
142
- #### `updateCell(tableId, rowIndex, colIndex, value, options)`
143
- Updates a specific cell value and styling.
144
- ```js
145
- ppt.updateCell('sales-table', 1, 0, 'New Product Name', {
146
- fill: 'FF0000', // HEX background color
147
- align: 'ctr', // Text alignment: 'l', 'ctr', 'r', 'just'
148
- fontSize: 14 // Font size in points
149
- });
150
- ```
151
-
152
- #### `mergeCells(options)` or `mergeCells(tableId, startRow, startCol, endRow, endCol)`
153
- Merges a rectangular range of cells. Supports horizontal, vertical, and block merges, moving cell texts to the origin cell (concatenated with newlines) and setting correct OpenXML `gridSpan` and `rowSpan` attributes.
154
- ```js
155
- // Config object signature (Recommended)
156
173
  ppt.mergeCells({
157
- slide: 3,
158
174
  tableId: 'sales-table',
159
175
  startRow: 1,
160
176
  startCol: 1,
161
- endRow: 3,
162
- endCol: 3
177
+ endRow: 2,
178
+ endCol: 2
163
179
  });
164
-
165
- // Legacy positional signature
166
- ppt.mergeCells('sales-table', 1, 1, 3, 3);
167
180
  ```
168
181
 
169
- #### `unmergeCells(options)` or `unmergeCells(tableId, startRow, startCol, endRow, endCol)`
170
- Unmerges cells, restoring original XML cell structures.
182
+ #### `unmergeCells(options)`
183
+ Splits a merged region back to its original individual cells, removing `gridSpan`, `rowSpan`, `hMerge`, and `vMerge` attributes.
171
184
  ```js
172
- // Cell-coordinate coordinate signature (Recommended)
173
185
  ppt.unmergeCells({
174
- slide: 3,
175
186
  tableId: 'sales-table',
176
- row: 2,
177
- col: 2
178
- });
179
-
180
- // Legacy positional signature
181
- ppt.unmergeCells('sales-table', 1, 1, 3, 3);
182
- ```
183
-
184
- #### `getMergedCells(tableId)`
185
- Scans the slide table and returns all active merged regions.
186
- ```js
187
- const merges = ppt.getMergedCells('sales-table');
188
- // Output: [ { startRow: 1, startCol: 1, endRow: 3, endCol: 3 } ]
189
- ```
190
-
191
- #### `validateMergeRegion(tableId, startRow, startCol, endRow, endCol)`
192
- Checks bounds and overlaps, returning detailed validation errors.
193
- ```js
194
- const report = ppt.validateMergeRegion('sales-table', 1, 1, 3, 3);
195
- console.log(report.valid); // true or false
196
- console.log(report.errors); // Array of error strings
197
- ```
198
-
199
- #### `isMergedCell(tableId, row, col)`
200
- Returns `true` if the cell at `(row, col)` is part of any merged region.
201
- ```js
202
- const merged = ppt.isMergedCell('sales-table', 2, 2);
203
- ```
204
-
205
- #### `getMergeParent(tableId, row, col)`
206
- Returns the coordinates `{ row, col }` of the top-left origin cell of the merge region containing `(row, col)`.
207
- ```js
208
- const parent = ppt.getMergeParent('sales-table', 2, 2); // { row: 1, col: 1 }
209
- ```
210
-
211
- #### `getMergeRegion(tableId, row, col)`
212
- Returns the merged region object `{ startRow, startCol, endRow, endCol }` containing `(row, col)`.
213
- ```js
214
- const region = ppt.getMergeRegion('sales-table', 2, 2);
215
- ```
216
-
217
- #### `splitMergedRegion(tableId, row, col)`
218
- Splits the merged region containing cell `(row, col)`.
219
- ```js
220
- ppt.splitMergedRegion('sales-table', 2, 2);
221
- ```
222
-
223
- #### `cloneMergedRegion(tableId, row, col, targetRow, targetCol)`
224
- Clones a merged region to another starting position, preserving cell text and formatting.
225
- ```js
226
- ppt.cloneMergedRegion('sales-table', 1, 1, 4, 1);
227
- ```
228
-
229
- #### Template-driven cell merges
230
- Support cell merging inside template updates dynamically via `colSpan`/`rowSpan` or `merge` arrays:
231
- ```js
232
- ppt.updateTable('sales-table', {
233
- rows: [
234
- ['Header 1', 'Header 2', 'Header 3'],
235
- ['Row 1 Col 1', { value: 'Spanned Cell', colSpan: 2 }],
236
- ['Row 2 Col 1', 'Row 2 Col 2', { value: 'Spanned V', rowSpan: 2 }]
237
- ],
238
- merge: [
239
- { startRow: 0, startCol: 0, endRow: 0, endCol: 2 }
240
- ]
187
+ row: 1,
188
+ col: 1
241
189
  });
242
190
  ```
243
191
 
244
- #### `autoFitTable(tableId)`
245
- Resizes columns to fit text width.
246
- ```js
247
- ppt.autoFitTable('sales-table');
248
- ```
249
-
250
- #### `resizeTable(tableId, width, height)`
251
- Resizes the bounding frame of the table. Width/height can be in EMUs or inches.
252
- ```js
253
- ppt.resizeTable('sales-table', 8.5, 4.2); // Dimensions in inches
254
- ```
255
-
256
- #### `getTables()`
257
- Lists tables in the current slide.
258
- ```js
259
- const tables = ppt.getTables();
260
- ```
261
-
262
192
  ---
263
193
 
264
- ### Chart Features
194
+ ### Chart Integration
265
195
 
266
196
  #### `updateChartData(chartId, data)`
267
- Updates a chart's categories, series, values, and embedded Excel workbook.
197
+ Overwrites chart categories and series values. Updates the embedded Excel spreadsheet to ensure the chart matches perfectly on refresh.
268
198
  ```js
269
199
  ppt.updateChartData('sales-chart', {
270
- categories: ['Q1', 'Q2', 'Q3'],
271
- series: [{ name: 'Sales', values: [100, 120, 150] }]
272
- });
273
- ```
274
-
275
- #### `replaceChartSeries(chartId, seriesIndex, newSeriesData)`
276
- Replaces values and name of a single series.
277
- ```js
278
- ppt.replaceChartSeries('sales-chart', 0, {
279
- name: 'Updated Series Name',
280
- values: [80, 95, 110]
200
+ categories: ['Q1', 'Q2', 'Q3', 'Q4'],
201
+ series: [
202
+ { name: 'Revenue', values: [100, 150, 180, 220] }
203
+ ]
281
204
  });
282
205
  ```
283
206
 
284
207
  #### `updateChartTitle(chartId, title)`
285
- Updates the chart's title.
286
- ```js
287
- ppt.updateChartTitle('sales-chart', 'Quarterly Revenue Performance');
288
- ```
289
-
290
- #### `updateChartCategories(chartId, categories)`
291
- Updates the chart categories.
292
- ```js
293
- ppt.updateChartCategories('sales-chart', ['Jan', 'Feb', 'Mar']);
294
- ```
295
-
296
- #### `getCharts()`
297
- Returns chart metadata from the slide.
298
- ```js
299
- const charts = ppt.getCharts();
300
- ```
301
-
302
- ---
303
-
304
- ### Text Features
305
-
306
- #### `replaceTextByTag(tag, value, options)`
307
- Replaces placeholders with custom values.
308
- ```js
309
- ppt.replaceTextByTag('username', 'Alice Cooper');
310
- ```
311
-
312
- #### `replaceMultiple(replacements, options)`
313
- Performs multiple text tag replacements.
314
- ```js
315
- ppt.replaceMultiple({
316
- 'date': '2026-06-02',
317
- 'location': 'New York'
318
- });
319
- ```
320
-
321
- #### `findText(text)`
322
- Searches for text in slide shape runs.
323
- ```js
324
- const matches = ppt.findText('DeepMind');
325
- ```
326
-
327
- #### `getTextElements()`
328
- Gets all raw text segments in the selected slide.
329
208
  ```js
330
- const elements = ppt.getTextElements();
209
+ ppt.updateChartTitle('sales-chart', 'Revenue Growth (2026)');
331
210
  ```
332
211
 
333
212
  ---
334
213
 
335
- ### Shape Features
336
-
337
- #### `updateShapeText(shapeId, text)`
338
- Updates text inside a shapes run.
339
- ```js
340
- ppt.updateShapeText('HeaderShape', 'Updated Slide Header');
341
- ```
342
-
343
- #### `cloneShape(shapeId, newShapeId, options)`
344
- Clones a shape and places it with offsets.
345
- ```js
346
- ppt.cloneShape('HeaderShape', 'HeaderShapeCopy', {
347
- offsetX: 1.0, // Offset X in inches
348
- offsetY: 0.5, // Offset Y in inches
349
- width: 5.0, // Resize width
350
- height: 2.0 // Resize height
351
- });
352
- ```
353
-
354
- #### `deleteShape(shapeId)`
355
- Deletes a shape.
356
- ```js
357
- ppt.deleteShape('HeaderShapeCopy');
358
- ```
359
-
360
- #### `getShapes()`
361
- Lists shapes on the slide.
362
- ```js
363
- const shapes = ppt.getShapes();
364
- ```
365
-
366
- ---
367
-
368
- ### Image Features
369
-
370
- #### `replaceImage(imageIdOrName, sourcePathOrBuffer)`
371
- Replaces an image file binary, keeping the layout.
372
- ```js
373
- await ppt.replaceImage('LogoImage', 'path/to/new-logo.png');
374
- ```
375
-
376
- #### `addImage(sourcePathOrBuffer, options)`
377
- Embeds a new image with layout options.
378
- ```js
379
- await ppt.addImage('path/to/badge.png', {
380
- x: 2.0, // Position X (inches)
381
- y: 1.5, // Position Y (inches)
382
- width: 3.0, // Width (inches)
383
- height: 3.0 // Height (inches)
384
- });
385
- ```
214
+ ## Performance Benchmarks
386
215
 
387
- #### `removeImage(imageIdOrName)`
388
- Deletes an image.
389
- ```js
390
- ppt.removeImage('Picture 1002');
391
- ```
216
+ Tested on a standard 50-slide enterprise presentation template:
392
217
 
393
- #### `getImages()`
394
- Lists images inside the slide.
395
- ```js
396
- const images = ppt.getImages();
397
- ```
218
+ | Operation | Execution Duration |
219
+ |:---|:---|
220
+ | Load PPTX Template | ~110ms |
221
+ | Find & Replace 20 Text Placeholders | ~2.5ms |
222
+ | XML Schema & Integrity Validation Check | ~14ms |
223
+ | Dynamic Row Insertion & Merging (15 rows) | ~3ms |
224
+ | Save and Re-package to PPTX ZIP | ~78ms |
398
225
 
399
226
  ---
400
227
 
401
- ### Validation System
228
+ ## FAQ & Troubleshooting
402
229
 
403
- #### `validatePresentation()`
404
- Audits the complete presentation.
405
- ```js
406
- const report = await ppt.validatePresentation();
407
- console.log('Errors:', report.errors);
408
- console.log('Warnings:', report.warnings);
409
- ```
230
+ ### PowerPoint displays a "Repair" prompt when opening my generated file
231
+ This is commonly caused by:
232
+ 1. **Missing overridden content type**: A new slide or chart XML was added but not registered in `[Content_Types].xml`.
233
+ 2. **Duplicate row identifiers**: If table rows are duplicated without generating a new unique `rowId` under `<a16:rowId>`.
234
+ 3. **Invalid relationship mapping**: An asset (like an image or worksheet) is referenced in slide XML but is missing from the slide's `.rels` file.
410
235
 
411
- #### `validateSlide(slideIndex)`
412
- Validates slide XML structure.
413
- ```js
414
- const report = await ppt.validateSlide(1);
415
- ```
236
+ *Fix*: Ensure you always use the public `saveToFile()` or `toBuffer()` helper functions, which automatically execute structural verification passes and update relationship chains.
416
237
 
417
- #### `validateTable(tableId)`
418
- Audits columns and duplicate rowIds in a table.
419
- ```js
420
- const report = await ppt.validateTable('sales-table');
421
- ```
422
-
423
- #### `validateRelationships(partPath)`
424
- Audits `.rels` relationship references.
425
- ```js
426
- const report = ppt.validateRelationships('ppt/slides/slide1.xml');
238
+ ### My text placeholders are not replacing
239
+ PowerPoint text editors segment formatting runs into separate XML elements. The text `{{title}}` may look normal in PowerPoint, but in XML it could be split into `<a:t>{{ti</a:t><a:t>tle}}</a:t>`.
240
+ *Fix*: You can enable logger output to see split tags:
241
+ ```bash
242
+ PPTX_LOG_LEVEL=debug node app.js
427
243
  ```
428
-
429
- ---
430
-
431
- ## ⚡ Performance Benchmarks
432
-
433
- Tested on a 50-slide presentation template:
434
-
435
- | Operation | Average Duration |
436
- |---|---|
437
- | Load presentation | ~120ms |
438
- | Replace 20 text tags | ~2ms |
439
- | Audit presentation structure | ~15ms |
440
- | Update table rows (10 rows) | ~3ms |
441
- | Rebuild ZIP and Save | ~80ms |
442
-
443
- ---
444
-
445
- ## ❓ FAQ
446
-
447
- #### Why use this over libraries like pptxgenjs or officegen?
448
- Those libraries generate presentations from scratch in code. `node-pptx-templater` is a **templating** engine. You create a beautiful template inside MS PowerPoint (applying themes, layout grids, animations, or styling), and then use this library to dynamically populate slides, update tables, and refresh chart values while preserving the design.
449
-
450
- #### How is chart styling preserved?
451
- We update only the `<c:cat>` (categories), `<c:val>` (values) XML nodes, and the underlying data sheet inside the embedded Excel workbook. PowerPoint reads these updated values and uses the template's pre-configured colors, font layouts, labels, and axes.
244
+ To fix this in PowerPoint, highlight the entire placeholder block, cut it, and paste it back as "Keep Text Only" to unify the XML text runs.
452
245
 
453
246
  ---
454
247
 
455
248
  ## 🤝 Contributing
456
249
 
457
- See [CONTRIBUTING.md](./CONTRIBUTING.md).
250
+ We welcome contributions! Please check out [CONTRIBUTING.md](./CONTRIBUTING.md) to get started.
458
251
 
459
252
  ```bash
460
253
  git clone https://github.com/jsuyog2/node-pptx-templater.git
@@ -467,4 +260,4 @@ npm test
467
260
 
468
261
  ## 📄 License
469
262
 
470
- MIT © [node-pptx-templater contributors](./LICENSE)
263
+ Licensed under the MIT License. © [node-pptx-templater contributors](./LICENSE)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "node-pptx-templater",
3
- "version": "1.0.3",
4
- "description": "Low-level PowerPoint OpenXML template engine for Node.js generate and edit PPTX files directly through XML manipulation without relying on PowerPoint generation libraries.",
3
+ "version": "1.0.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",
7
7
  "exports": {
@@ -43,7 +43,16 @@
43
43
  "report",
44
44
  "generator",
45
45
  "nodejs",
46
- "esm"
46
+ "powerpoint-automation",
47
+ "pptx-template-engine",
48
+ "merge-cells",
49
+ "table-merge",
50
+ "chart-update",
51
+ "dynamic-slides",
52
+ "mail-merge",
53
+ "report-generator",
54
+ "xml-manipulation",
55
+ "pptx-editor"
47
56
  ],
48
57
  "author": {
49
58
  "name": "node-pptx-templater contributors"