node-pptx-templater 1.0.21 → 1.1.1

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/README.md CHANGED
@@ -1,49 +1,34 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/jsuyog2/node-pptx-templater/main/docs/logo.svg" alt="PPTXForge Logo" width="550" max-width="100%">
2
+ <img src="https://raw.githubusercontent.com/jsuyog2/node-pptx-templater/main/assets/logo.png" alt="node-pptx-templater logo" width="160">
3
3
  </p>
4
4
 
5
- <h1 align="center">node-pptx-templater (PPTXForge Engine)</h1>
5
+ <h1 align="center">node-pptx-templater</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>The High-Performance, Secure OpenXML PowerPoint Template Engine for Node.js</strong>
8
+ <strong>High-performance OpenXML PowerPoint template engine for Node.js</strong>
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
12
  <a href="https://www.npmjs.com/package/node-pptx-templater"><img src="https://img.shields.io/npm/v/node-pptx-templater.svg?style=flat-square&color=6366f1" alt="npm version"></a>
13
- <a href="https://github.com/jsuyog2/node-pptx-templater/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/jsuyog2/node-pptx-templater/ci.yml?branch=main&style=flat-square&color=34d399" alt="CI Build Status"></a>
14
- <a href="https://bundlephobia.com/package/node-pptx-templater"><img src="https://img.shields.io/bundlephobia/min/node-pptx-templater?style=flat-square&color=ec4899" alt="Bundle Size"></a>
13
+ <a href="https://github.com/jsuyog2/node-pptx-templater/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/jsuyog2/node-pptx-templater/ci.yml?branch=main&style=flat-square&color=34d399" alt="CI"></a>
15
14
  <a href="https://www.npmjs.com/package/node-pptx-templater"><img src="https://img.shields.io/npm/dm/node-pptx-templater.svg?style=flat-square&color=a855f7" alt="Downloads"></a>
16
- <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square" alt="License: MIT"></a>
17
- <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen?style=flat-square" alt="Node.js Version"></a>
15
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square" alt="MIT License"></a>
16
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen?style=flat-square" alt="Node.js 18+"></a>
18
17
  </p>
19
18
 
20
- ---
21
-
22
- ## ⚡ Why PPTXForge (`node-pptx-templater`)?
23
-
24
- Traditional slide deck automation requires assembling slides shape-by-shape in verbose code blocks. This is fragile, difficult to maintain, and strips away the power of visual design tools like Microsoft PowerPoint, Keynote, or Google Slides.
25
-
26
- **PPTXForge takes a visual-first approach: Design visually in PowerPoint, populate dynamically in Node.js.**
27
-
28
- You design your layouts, tables, fonts, brand styles, charts, and animations inside PowerPoint, and insert placeholders like `{{customer_name}}`, `{{revenue_chart}}`, or `{{team_table}}`. The PPTXForge engine parses the OpenXML presentation, heals broken text run segmentations, updates Excel data workbook caches, merges drawing cells, and scales slides securely in pure JavaScript with zero external office dependencies.
19
+ <p align="center">
20
+ <a href="https://jsuyog2.github.io/node-pptx-templater/"><strong>📖 Full Documentation →</strong></a>
21
+ </p>
29
22
 
30
23
  ---
31
24
 
32
- ## Enterprise-Grade Core Features
25
+ Design your presentations visually in PowerPoint. Populate them dynamically in Node.js.
33
26
 
34
- * 🚀 **Zero Native/Office/Java Dependencies**: Pure CommonJS JavaScript implementation. Runs efficiently on AWS Lambda, Vercel Edge, Netlify, and Cloudflare Workers.
35
- * 🛡️ **Hardened XML Security**: Fully immune to Billion Laughs (XML bombs), XXE (XML External Entity Injection), and parser crashes due to oversized expansions.
36
- * 🧩 **Text Run Fragmentation Healing**: Solves the split-tag issue. PowerPoint splits `{{placeholders}}` into fragmented `<a:r>` nodes; our parser unifies and replaces them while keeping original formatting intact.
37
- * 📊 **Excel Cache Synchronized Charting**: Supports Bar, Line, Pie, Doughnut, Area, and Scatter charts. Not only updates the visual XML coordinates but also synchronizes data points inside the underlying embedded Excel spreadsheets (`ppt/embeddings/`) to bypass PowerPoint's "Update Data" warnings.
38
- * 🏷️ **Chart Data Labels & Value From Cells**: Configure custom arrays, dynamic category maps, rich templates, positions (insideEnd, bestFit, center), and custom styles (fonts, colors, weight) and serialize them directly to the underlying Excel backing sheet.
39
- * 📋 **DrawingML Table Cell Merging**: Easily configure horizontal spans (`gridSpan`/`hMerge`), vertical spans (`rowSpan`/`vMerge`), and rectangular blocks. Injects unique `rowId` hashes to maintain relationship integrity.
40
- * 🥞 **Z-Order Layer Stacking**: Reorder shapes, images, charts, and tables programmatically. Simulates PowerPoint's "Bring to Front" and "Send to Back" commands directly in the slide's `<p:spTree>`.
41
- * 🎛️ **Slide Management**: Duplicate, delete, reorder slides, or import slides from external decks with automatic media and theme deduplication.
42
- * 🔍 **OPC Package Verification**: Comprehensive check suite for content type overrides, relationship integrity, and XML structure before final output.
27
+ `node-pptx-templater` parses OpenXML directly — no native office dependencies, no Java, no Electron. Pure JavaScript that runs on AWS Lambda, Vercel Edge, and Cloudflare Workers.
43
28
 
44
29
  ---
45
30
 
46
- ## 📦 Installation
31
+ ## Installation
47
32
 
48
33
  ```bash
49
34
  npm install node-pptx-templater
@@ -51,2292 +36,246 @@ npm install node-pptx-templater
51
36
 
52
37
  ---
53
38
 
54
- ## 🚀 Quick Start Guide
55
-
56
- Generate a formatted presentation report from a visually designed template in under 60 seconds:
39
+ ## Quick Start
57
40
 
58
41
  ```javascript
59
42
  const { PPTXTemplater } = require('node-pptx-templater');
60
43
 
61
- async function generateReport() {
62
- // 1. Load the presentation template
63
- const ppt = await PPTXTemplater.load('monthly_report_template.pptx');
64
-
65
- // 2. Select slide 1 and execute standard text replacements
66
- ppt.useSlide(1)
67
- .replaceTextByTag('title', 'Q2 Business Overview')
68
- .replaceMultiple({
69
- client: 'Acme Corporation',
70
- analyst: 'Sarah Jenkins',
71
- date: 'June 2026'
72
- });
73
-
74
- // 3. Update Excel-backed chart data on Slide 2
75
- ppt.useSlide(2)
76
- .updateChartData('revenue-chart', {
77
- categories: ['April', 'May', 'June'],
78
- series: [
79
- { name: 'Target', values: [120000, 150000, 180000] },
80
- { name: 'Actual', values: [125000, 162000, 195000] }
81
- ]
82
- });
83
-
84
- // 3b. Configure custom chart data labels with templates and styling
85
- ppt.useSlide(2)
86
- .updateDataLabels('revenue-chart', {
87
- series: 0,
88
- template: '{category}: {value}',
89
- position: 'insideEnd',
90
- labelStyle: { fontFamily: 'Arial', fontSize: 10, bold: true }
91
- });
92
-
93
- // 4. Update table structure with cell merges and colors on Slide 3
94
- ppt.useSlide(3)
95
- .updateTable('performance-table', [
96
- ['Region', 'Growth Metric', { value: 'Status / Notes', colSpan: 2 }],
97
- ['North Region', '+12.4%', { value: 'Exceeded Target', align: 'ctr', fill: '10b981' }, ''],
98
- ['South Region', '-3.1%', { value: 'Under Review', align: 'ctr', fill: 'f59e0b' }, '']
99
- ]);
100
-
101
- // 5. Duplicate a layout and bring an overlay element to the front
102
- ppt.duplicateSlide(3, 4);
103
- ppt.useSlide(4)
104
- .bringToFront('OverlayLogo')
105
- .replaceTextByTag('title', 'Duplicate Region Report');
106
-
107
- // 6. Save package without PowerPoint Repair Warnings
108
- await ppt.saveToFile('./output/q2_business_report.pptx');
109
- console.log('Report generated successfully!');
110
- }
111
-
112
- generateReport().catch(console.error);
113
- ```
114
-
115
- ## 📂 PowerPoint XML Folder Templates
116
-
117
- Instead of loading and saving standard compiled `.pptx` ZIP files, the library natively supports working with uncompressed PowerPoint OpenXML directories. This is extremely useful for server environments and development setups, bypassing ZIP compression/decompression overhead and resolving relationships relative to the unzipped structure.
118
-
119
- ### 1. Load from XML Folder Template
120
-
121
- You can load a template directly from a folder directory or `presentation.xml` entry point:
122
-
123
- ```javascript
124
- const { PPTXTemplater, PPTXTemplate } = require('node-pptx-templater');
125
-
126
- // Load using the directory root path (auto-detects ppt/presentation.xml)
127
- const ppt = await PPTXTemplater.load('./monthly-template-folder');
128
-
129
- // Load using fromPresentationXml with a configuration object
130
- const ppt2 = await PPTXTemplate.fromPresentationXml({
131
- presentation: './ppt/presentation.xml',
132
- root: './template'
133
- });
134
- ```
135
-
136
- ### 2. Save/Export directly to XML Folder
137
-
138
- You can export the modified presentation back to an uncompressed folder structure on disk:
139
-
140
- ```javascript
141
- await ppt.saveToFolder('./output-template-folder');
142
- ```
143
-
144
- This generates:
145
- ```text
146
- output-template-folder/
147
- ├── [Content_Types].xml
148
- ├── _rels/
149
- ├── ppt/
150
- │ ├── presentation.xml
151
- │ ├── _rels/
152
- │ ├── slides/
153
- │ ├── slideLayouts/
154
- │ ├── slideMasters/
155
- │ └── theme/
156
- └── docProps/
157
- ```
158
-
159
- ### 3. Folder Mode Performance Benefits
160
-
161
- Our benchmark results compare standard ZIP-based templates with uncompressed XML folder workflows:
162
- * **Concurrency Throughput**: Up to **1.4x faster** under parallel request stress due to eliminated ZIP compression CPU locks.
163
- * **Heap Memory Footprint**: Reduces memory overhead by avoiding full in-memory ZIP archives.
164
-
165
- ### 4. Validation
166
-
167
- Ensure XML directory templates are correct and contain no orphan relations:
168
-
169
- ```javascript
170
- const report = await ppt.validatePresentationXml();
171
- if (!report.valid) {
172
- console.error('Errors found:', report.errors);
173
- }
174
- ```
175
-
176
- ### 5. PPTX Extraction & Rebuilding Utilities
44
+ const ppt = await PPTXTemplater.load('template.pptx');
177
45
 
178
- You can programmatically extract standard zipped `.pptx` archives into OpenXML folder templates or compile them back. Target directories are created automatically:
46
+ // Replace text placeholders
47
+ ppt.useSlide(1)
48
+ .replaceMultiple({ '{{title}}': 'Q2 Report', '{{date}}': 'June 2026' });
179
49
 
180
- #### Extract PPTX to Folder Template
181
- ```javascript
182
- const { PPTXTemplate } = require('node-pptx-templater');
50
+ // Update chart data (syncs the embedded Excel workbook too)
51
+ ppt.useSlide(2)
52
+ .updateChart('revenue-chart', {
53
+ categories: ['April', 'May', 'June'],
54
+ series: [{ name: 'Revenue', values: [125000, 162000, 195000] }]
55
+ });
183
56
 
184
- await PPTXTemplate.extractPptx('./sample.pptx', './output/template', { overwrite: true });
185
- ```
57
+ // Update table
58
+ ppt.useSlide(3)
59
+ .updateTable('SalesTable', {
60
+ rows: [['North', '$1.2M', '↑15%'], ['South', '$1.8M', '↑22%']]
61
+ });
186
62
 
187
- #### Rebuild PPTX from Folder Template
188
- ```javascript
189
- await PPTXTemplate.buildPptx('./templates/sample', './output.pptx');
63
+ await ppt.saveToFile('output.pptx');
190
64
  ```
191
65
 
192
66
  ---
193
67
 
194
- ## 📋 OpenXML Presentation Architecture
195
-
196
- A `.pptx` file is an Open Packaging Convention (OPC) ZIP package containing structured XML schemas:
197
-
198
- ```text
199
- PPTX Archive Structure:
200
- ├── [Content_Types].xml # MIME type registry for all zip contents
201
- ├── _rels/
202
- │ └── .rels # Package-level relationship mappings
203
- └── ppt/
204
- ├── presentation.xml # Global presentation slide order and layouts
205
- ├── slides/
206
- │ ├── slide1.xml # DrawingML elements, text runs, and shapes
207
- │ └── _rels/
208
- │ └── slide1.xml.rels # Resource mappings (images, charts, tables)
209
- ├── media/ # Image and SVG database
210
- └── embeddings/ # Embedded Excel books backing charts
211
- ```
212
-
213
- ### Unifying Text Run Segmentations
214
- Under the hood, slide template text is represented as runs of text (`<a:r>`). PowerPoint's parser often breaks a single tag `{{name}}` into separate segments:
215
- ```xml
216
- <!-- Split layout generated by PowerPoint -->
217
- <a:r><a:t>{{n</a:t></a:r>
218
- <a:r><a:t>ame}}</a:t></a:r>
219
- ```
220
- PPTXForge parses the XML structure, identifies layout boundaries, merges text nodes back into a single element, and applies replacements while preserving font sizes, colors, and styling rules.
221
-
222
- ### Preventing PPTX "Repair Presentation" Warnings
223
- Naively duplicating rows in slide tables can leave duplicate `rowId` values or break cell mappings, causing PowerPoint to crash or prompt a repair screen. PPTXForge automatically re-allocates unique `rowId` hashes and formats `gridSpan` / `rowSpan` coordinates in compliance with standard Office OpenXML (OOXML) regulations.
68
+ ## Features
69
+
70
+ | Category | Capabilities |
71
+ |---|---|
72
+ | **Text** | Replace placeholders, search & replace, rich text, bullet lists |
73
+ | **Tables** | Update cells, add/insert/remove rows, merge cells, extract data as JSON |
74
+ | **Charts** | Update data, sync Excel workbook, custom data labels, series management |
75
+ | **Images** | Replace, add, remove images; set position, size, rotation, crop |
76
+ | **Shapes** | Add, update, clone, remove shapes; set fill, text, position |
77
+ | **Cell Shapes** | Add shapes inside table cells with automatic bounds calculation |
78
+ | **Slides** | Duplicate, move, delete, import/export, clone, reorder |
79
+ | **Layer Ordering** | Bring to front, send to back, set Z-index, swap, sort |
80
+ | **Hyperlinks** | URL links, slide navigation, shape and image links |
81
+ | **XML Folder** | Extract to folder, edit XML directly, rebuild to PPTX |
82
+ | **Validation** | Structural validation, relationship checks, auto-repair |
83
+ | **Performance** | Template caching, async streaming, profiling |
224
84
 
225
85
  ---
226
86
 
227
- ## 📊 Reading Table Data & JSON Extraction
228
-
229
- PPTXForge allows you to read table data from your template and return it as structured JSON objects or raw arrays. This is extremely useful for reverse-engineering data or verifying layouts.
230
-
231
- ### 1. Object-Based Extraction (Default)
232
- By default, the first row is treated as headers, and subsequent rows are returned as objects keyed by header names. Merged cells automatically resolve to their parent cell's value:
233
- ```javascript
234
- const rows = await ppt.getTableRows('SalesTable');
235
- // Returns:
236
- // [
237
- // { region: 'North', sales: '1200', growth: '15%' },
238
- // { region: 'South', sales: '1800', growth: '22%' }
239
- // ]
240
- ```
87
+ ## Logging
241
88
 
242
- ### 2. Raw Extraction
243
- Return a raw 2D array of string values (excluding the header row) by passing `{ raw: true }`:
244
- ```javascript
245
- const rows = await ppt.getTableRows('SalesTable', { raw: true });
246
- // Returns:
247
- // [
248
- // ['North', '1200', '15%'],
249
- // ['South', '1800', '22%']
250
- // ]
251
- ```
89
+ The library is **completely silent by default**. Enable logging when needed:
252
90
 
253
- ### 3. Including Table Metadata
254
- Pass `{ includeMetadata: true }` to retrieve row counts, column counts, and the list of merged cell ranges alongside the rows:
255
91
  ```javascript
256
- const result = await ppt.getTableRows('SalesTable', { includeMetadata: true });
257
- // Returns:
258
- // {
259
- // rows: [...],
260
- // rowCount: 10,
261
- // columnCount: 5,
262
- // mergedCells: [ { startRow: 1, startCol: 0, endRow: 2, endCol: 0 }, ... ]
263
- // }
264
- ```
265
-
266
- ---
267
-
268
- ## 📈 Nested Table Rows & Rowspan Support
92
+ // At load time
93
+ const ppt = await PPTXTemplater.load('template.pptx', { logLevel: 'debug' });
269
94
 
270
- When building financial sheets, invoices, or hierarchical dashboards, you often need to stack multiple rows vertically inside a single column while spanning cells in other columns. PPTXForge supports nested arrays in `addTableRow()` to automatically handle:
271
- - Proportional height scaling.
272
- - Vertical merge (`vMerge`) and row span (`rowSpan`) generation.
273
- - Dynamic layout adjustments.
95
+ // Globally (affects all instances)
96
+ PPTXTemplater.setLogLevel('debug');
274
97
 
275
- ### 1. Vertical Row Nesting Example
276
- ```javascript
277
- await ppt.addTableRow('Table1', [
278
- 'Region',
279
- ['Sales', '1200'],
280
- ['Growth', '15%']
281
- ]);
282
- ```
283
- Generates:
284
- ```text
285
- +---------+---------+---------+
286
- | Region | Sales | Growth |
287
- | | 1200 | 15% |
288
- +---------+---------+---------+
289
- ```
98
+ // Instance shortcut
99
+ ppt.enableDebug();
290
100
 
291
- ### 2. Deep Nesting Example
292
- ```javascript
293
- await ppt.addTableRow('Table1', [
294
- 'Parent',
295
- [
296
- 'Child 1',
297
- 'Child 2',
298
- 'Child 3'
299
- ]
300
- ]);
101
+ // Suppress everything (explicit)
102
+ PPTXTemplater.setLogLevel('silent');
301
103
  ```
302
- Generates 3 sub-rows where column 0 automatically spans all 3 rows.
303
104
 
304
- ### 3. Merge Strategies
305
- Configure merge behavior via `options.mergeStrategy`:
306
- - `'auto'` (default): Creates structural merges from nested arrays, and additionally merges consecutive duplicate values in the same column.
307
- - `'rowspan'`: Creates structural rowspan/merges strictly from the nested array structure.
308
- - `'none'`: Pads columns to match the target generated height but does not merge cells (leaving them as individual cells).
309
-
310
- ```javascript
311
- await ppt.addTableRow('Table1', data, { mergeStrategy: 'rowspan' });
312
- ```
105
+ Supported levels: `verbose` | `debug` | `info` | `warn` (default) | `error` | `silent`
313
106
 
314
107
  ---
315
108
 
316
- ## 📊 Feature Comparison Matrix
317
-
318
- Compare PPTXForge with other popular PowerPoint automation libraries:
319
-
320
- | Feature / Metric | **node-pptx-templater** (PPTXForge) | **pptxgenjs** | **pptx-template** | **pptx-automizer** | **officegen** |
321
- | :--- | :---: | :---: | :---: | :---: | :---: |
322
- | **Automation Flow** | **Template-based** | Code-based | Template-based | Template-based | Code-based |
323
- | **No Office/Java Dependency** | **Yes** (Pure JS) | Yes | Yes | Yes | Yes |
324
- | **Bypass Corruption/Repair Alerts** | **Yes** (RowId sync) | Yes | No (Row duplicate breaks) | Yes | Yes |
325
- | **Heal Text Run Fragmentation** | **Yes** | N/A | No (Tags break) | Yes | N/A |
326
- | **Synchronized Excel Chart Updates** | **Yes** (Direct sync) | Yes | No (Text updates only) | Yes | Yes |
327
- | **Horizontal & Vertical Cell Merge** | **Yes** (gridSpan/rowSpan) | Yes | No | No | No |
328
- | **Z-Order Layer Reordering** | **Yes** (Front/Back) | No | No | Yes | No |
329
- | **External Slide Imports** | **Yes** (Deduplicated) | No | No | Yes | No |
330
-
331
- <!-- API_REFERENCE_START -->
332
-
333
- ### Tables API
334
-
335
- #### `updateTable(tableId, rows)`
336
- Replaces table rows with new data in the selected slide(s). Preserves borders, merged cells, fonts, colors, and alignment from the template.
337
-
338
- * **Arguments**:
339
- * `tableId` (`string`): Table name or shape ID.
340
- * `rows` (`string[][]`): 2D array of cell values (row × col).
341
- * **Returns**: `PPTXTemplater` - this (chainable)
342
-
343
- ```javascript
344
- ppt.useSlide(1).updateTable('summary-table', [
345
- ['Item', 'Value'],
346
- ['Widgets', '1,200'],
347
- ['Gadgets', '850']
348
- ]);
349
- ```
350
-
351
- #### `addCellShape(tableId, rowIndex, colIndex, options)`
352
- Dynamically adds a shape inside a table cell based on cell coordinates.
353
-
354
- * **Arguments**:
355
- * `tableId` (`string`): Table name or shape ID.
356
- * `rowIndex` (`number`): 0-based row index.
357
- * `colIndex` (`number`): 0-based column index.
358
- * `options` (`Object`): Shape configuration options.
359
- * **Returns**: `this` - The chainable presentation templater instance.
360
-
361
- ```javascript
362
- await ppt.addCellShape('Table', 1, 2, { type: 'circle', fill: '#10B981' });
363
- ```
364
-
365
- #### `updateCellShape(tableId, rowIndex, colIndex, shapeIndex, options)`
366
- Updates an existing shape inside a table cell.
367
-
368
- * **Arguments**:
369
- * `tableId` (`string`): Table name or shape ID.
370
- * `rowIndex` (`number`): 0-based row index.
371
- * `colIndex` (`number`): 0-based column index.
372
- * `shapeIndex` (`number`): 0-based shape index in the cell.
373
- * `options` (`Object`): Shape configuration properties to update.
374
- * **Returns**: `this` - The chainable presentation templater instance.
375
-
376
- ```javascript
377
- await ppt.updateCellShape('Table', 1, 2, 0, { fill: '#EF4444' });
378
- ```
379
-
380
- #### `removeCellShape(tableId, rowIndex, colIndex, shapeIndex)`
381
- Removes a shape from a table cell.
382
-
383
- * **Arguments**:
384
- * `tableId` (`string`): Table name or shape ID.
385
- * `rowIndex` (`number`): 0-based row index.
386
- * `colIndex` (`number`): 0-based column index.
387
- * `shapeIndex` (`number`): 0-based shape index in the cell.
388
- * **Returns**: `this` - The chainable presentation templater instance.
389
-
390
- ```javascript
391
- await ppt.removeCellShape('Table', 1, 2, 0);
392
- ```
393
-
394
- #### `getCellShape(tableId, rowIndex, colIndex, shapeIndex)`
395
- Discovers and retrieves details of an existing cell shape on the targeted slide.
396
-
397
- * **Arguments**:
398
- * `tableId` (`string`): Table name or shape ID.
399
- * `rowIndex` (`number`): 0-based row index.
400
- * `colIndex` (`number`): 0-based column index.
401
- * `shapeIndex` (`number`): 0-based shape index in the cell.
402
- * **Returns**: `Object|null` - Shape details object, or null if not found.
403
-
404
- ```javascript
405
- const shape = ppt.getCellShape('Table', 1, 2, 0);
406
- ```
407
-
408
- #### `getCellBounds(tableId, rowIndex, colIndex)`
409
- Retrieves final rendered bounds of a table cell in pixels.
410
-
411
- * **Arguments**:
412
- * `tableId` (`string`): Table name or shape ID.
413
- * `rowIndex` (`number`): 0-based row index.
414
- * `colIndex` (`number`): 0-based column index.
415
- * **Returns**: `Object|null` - Cell bounds { x, y, width, height } in pixels, or null.
416
-
417
- ```javascript
418
- const bounds = ppt.getCellBounds('summary-table', 1, 1);
419
- ```
420
-
421
- #### `getCellPosition(tableId, rowIndex, colIndex)`
422
- Retrieves final rendered position of a table cell in pixels.
423
-
424
- * **Arguments**:
425
- * `tableId` (`string`): Table name or shape ID.
426
- * `rowIndex` (`number`): 0-based row index.
427
- * `colIndex` (`number`): 0-based column index.
428
- * **Returns**: `Object|null` - Cell position { row, column, x, y } in pixels, or null.
429
-
430
- ```javascript
431
- const pos = ppt.getCellPosition('summary-table', 1, 1);
432
- ```
433
-
434
- #### `getTableRows(())`
435
- Delegates core actions to slide element sub-managers.
436
-
437
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
438
-
439
- ```javascript
440
- const rows = await ppt.getTableRows('SalesTable');
441
- ```
442
-
443
- #### `addTableRow(())`
444
- Delegates core actions to slide element sub-managers.
445
-
446
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
447
-
448
- ```javascript
449
- ppt.useSlide(1).addTableRow('data-table', ['John Doe', 'Sales Manager', '$120k']);
450
- ```
451
-
452
- #### `removeTableRow(())`
453
- Delegates core actions to slide element sub-managers.
454
-
455
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
456
-
457
- ```javascript
458
- ppt.useSlide(1).removeTableRow('data-table', 2);
459
- ```
460
-
461
- #### `insertTableRow(())`
462
- Delegates core actions to slide element sub-managers.
463
-
464
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
465
-
466
- ```javascript
467
- ppt.useSlide(1).insertTableRow(());
468
- ```
469
-
470
- #### `cloneTableRow(())`
471
- Delegates core actions to slide element sub-managers.
472
-
473
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
474
-
475
- ```javascript
476
- ppt.useSlide(1).cloneTableRow(());
477
- ```
478
-
479
- #### `updateCell(())`
480
- Delegates core actions to slide element sub-managers.
481
-
482
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
483
-
484
- ```javascript
485
- ppt.useSlide(1).updateCell(());
486
- ```
487
-
488
- #### `mergeCells(())`
489
- Delegates core actions to slide element sub-managers.
490
-
491
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
492
-
493
- ```javascript
494
- ppt.useSlide(1).mergeCells('metrics-table', 1, 1, 2, 2);
495
- ```
496
-
497
- #### `unmergeCells(())`
498
- Delegates core actions to slide element sub-managers.
499
-
500
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
501
-
502
- ```javascript
503
- ppt.useSlide(1).unmergeCells('metrics-table', 1, 1, 2, 2);
504
- ```
505
-
506
- #### `getMergedCells(())`
507
- Delegates core actions to slide element sub-managers.
508
-
509
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
510
-
511
- ```javascript
512
- ppt.useSlide(1).getMergedCells(());
513
- ```
514
-
515
- #### `validateMergeRegion(())`
516
- Delegates core actions to slide element sub-managers.
517
-
518
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
519
-
520
- ```javascript
521
- ppt.useSlide(1).validateMergeRegion(());
522
- ```
523
-
524
- #### `isMergedCell(())`
525
- Delegates core actions to slide element sub-managers.
526
-
527
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
528
-
529
- ```javascript
530
- ppt.useSlide(1).isMergedCell(());
531
- ```
532
-
533
- #### `getMergeParent(())`
534
- Delegates core actions to slide element sub-managers.
535
-
536
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
537
-
538
- ```javascript
539
- ppt.useSlide(1).getMergeParent(());
540
- ```
541
-
542
- #### `getMergeRegion(())`
543
- Delegates core actions to slide element sub-managers.
544
-
545
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
546
-
547
- ```javascript
548
- ppt.useSlide(1).getMergeRegion(());
549
- ```
550
-
551
- #### `splitMergedRegion(())`
552
- Delegates core actions to slide element sub-managers.
553
-
554
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
555
-
556
- ```javascript
557
- ppt.useSlide(1).splitMergedRegion(());
558
- ```
559
-
560
- #### `cloneMergedRegion(())`
561
- Delegates core actions to slide element sub-managers.
562
-
563
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
564
-
565
- ```javascript
566
- ppt.useSlide(1).cloneMergedRegion(());
567
- ```
568
-
569
- #### `autoFitTable(())`
570
- Delegates core actions to slide element sub-managers.
571
-
572
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
573
-
574
- ```javascript
575
- ppt.useSlide(1).autoFitTable(());
576
- ```
577
-
578
- #### `resizeTable(())`
579
- Delegates core actions to slide element sub-managers.
580
-
581
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
582
-
583
- ```javascript
584
- ppt.useSlide(1).resizeTable(());
585
- ```
586
-
587
- #### `getTables(())`
588
- Delegates core actions to slide element sub-managers.
589
-
590
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
591
-
592
- ```javascript
593
- ppt.useSlide(1).getTables(());
109
+ ## Examples
110
+
111
+ The [`examples/`](./examples) directory contains runnable scripts for every major feature:
112
+
113
+ | Script | What it demonstrates |
114
+ |---|---|
115
+ | `basic-usage.js` | Text, charts, tables, links end-to-end workflow |
116
+ | `chart-update.js` | Multi-series chart updates with Excel sync |
117
+ | `chart-data-labels.js` | Custom data label formatting and positioning |
118
+ | `table-update.js` | Cell updates, row management, merging |
119
+ | `slide-selection.js` | Slide operations duplicate, move, delete |
120
+ | `image-operations.js` | Add, replace, remove images |
121
+ | `shape-operations.js` | Shape lifecycle add, update, clone, delete |
122
+ | `z-order.js` | Layer ordering bring/send, swap, set Z-index |
123
+ | `slide-import.js` | Import/export slides between presentations |
124
+ | `text-search.js` | Find text, replace multiple, update named shapes |
125
+ | `table-extraction.js` | Extract table data as JSON (all 3 modes) |
126
+ | `nested-table-rows.js` | Nested rows with rowspan / auto / none strategies |
127
+ | `xml-folder-workflow.js` | Extract → edit XML → rebuild PPTX |
128
+
129
+ Run any example:
130
+ ```bash
131
+ npm run example:basic
132
+ npm run example:images
133
+ npm run example:shapes
134
+ # ... etc
594
135
  ```
595
136
 
596
137
  ---
597
138
 
598
- ### Charts API
599
-
600
- #### `updateChart(chartId, data)`
601
- Updates chart data in the selected slide(s). Finds charts by their name/ID and updates categories, series, and values. Preserves original chart styles, themes, and formatting. Supports inline custom data labels by passing objects in the format `{ data: number, label: string }` instead of numbers.
602
-
603
- * **Arguments**:
604
- * `chartId` (`string`): Chart name or relationship ID.
605
- * `data` (`ChartData`): New chart data.
606
- * `data.categories` (`string[]`): Category labels (X-axis).
607
- * `data.series` (`SeriesData[]`): Data series array.
608
- * `data.series[].name` (`string`): Series name.
609
- * `data.series[].values` (`number[]|object[]`): Data values (numbers or label objects).
610
- * **Returns**: `PPTXTemplater` - this (chainable)
611
-
612
- ```javascript
613
- ppt.useSlide(1).updateChart(chartId, data);
614
- ```
615
-
616
- #### `validateCharts()`
617
- Validates all charts in the presentation to ensure they are not corrupted. Checks XML, caches, and embedded workbook references.
618
-
619
- * **Returns**: `Promise<Object>` - Validation results for charts.
620
-
621
- ```javascript
622
- ppt.useSlide(1).validateCharts();
623
- ```
624
-
625
- #### `repairCharts()`
626
- Repairs common chart corruption issues such as broken caches, missing embedded workbooks, or orphan nodes.
139
+ ## Core Concepts
627
140
 
628
- * **Returns**: `Promise<PPTXTemplater>` - this
141
+ ### Template Design
142
+ Create your template in PowerPoint. Use `{{placeholder}}` tags in text boxes, name your shapes, tables, and charts clearly — the library finds them by name.
629
143
 
144
+ ### Slide Targeting
630
145
  ```javascript
631
- ppt.useSlide(1).repairCharts();
146
+ ppt.useSlide(2) // Target slide 2
147
+ ppt.useAllSlides() // Target all slides
632
148
  ```
633
149
 
634
- #### `getChartLabelPositions(chartId)`
635
- Retrieves the exact coordinate positions of all data labels for a chart on the active slide. Calculates absolute layout limits in EMUs (English Metric Units).
636
-
637
- * **Arguments**:
638
- * `chartId` (`string`):
639
- * **Returns**: `Promise<Array<{series: string, category: string, seriesIndex: number, categoryIndex: number, value: number, x: number, y: number, width: number, height: number` -
640
-
150
+ ### Chaining
151
+ Most methods return `this`, enabling fluent chains:
641
152
  ```javascript
642
- const positions = await ppt.useSlide(1).getChartLabelPositions('SalesChart');
153
+ ppt.useSlide(1)
154
+ .replaceTextByTag('{{name}}', 'Alice')
155
+ .updateShapePosition('logo', { x: 500000, y: 200000 })
156
+ .bringToFront('logo');
643
157
  ```
644
158
 
645
- #### `getChartBarPositions(chartId)`
646
- Retrieves the exact coordinate positions of all bars/columns for a chart on the active slide. Calculates absolute layout limits in EMUs (English Metric Units).
647
-
648
- * **Arguments**:
649
- * `chartId` (`string`):
650
- * **Returns**: `Promise<Array<{series: string, category: string, seriesIndex: number, categoryIndex: number, value: number, x: number, y: number, width: number, height: number` -
651
-
159
+ ### Table Data Extraction
652
160
  ```javascript
653
- const bars = await ppt.useSlide(1).getChartBarPositions('SalesChart');
654
- ```
655
-
656
- #### `addTextAtPosition(options)`
657
- Adds a textbox shape at a specific EMU coordinate position on targeted slides. Supports custom font styling and alignment configuration.
161
+ // Object array (header row = keys)
162
+ const rows = await ppt.getTableRows('SalesTable');
163
+ // → [{ region: 'North', sales: '1200' }, ...]
658
164
 
659
- * **Arguments**:
660
- * `options` (`Object`):
661
- * `options.text` (`string`):
662
- * `options.x` (`number`):
663
- * `options.y` (`number`):
664
- * `[options.width=1200000]` (`number`):
665
- * `[options.height=300000]` (`number`):
666
- * `[options.style]` (`Object`):
667
- * **Returns**: `this` - The chainable presentation engine instance.
165
+ // Raw string arrays
166
+ const raw = await ppt.getTableRows('SalesTable', { raw: true });
167
+ // [['North', '1200'], ...]
668
168
 
669
- ```javascript
670
- ppt.useSlide(1).addTextAtPosition({
671
- text: 'Label',
672
- x: 1000000,
673
- y: 1000000
674
- });
169
+ // With metadata
170
+ const meta = await ppt.getTableRows('SalesTable', { includeMetadata: true });
171
+ // → { rows: [...], rowCount: 5, columnCount: 3, mergedCells: [] }
675
172
  ```
676
173
 
677
- #### `addTextNearChartLabel(options)`
678
- Dynamically places textboxes next to a chart's data labels with vertical collision avoidance. Textboxes are positioned either on the left or right of the chart area, vertically aligned with their corresponding label.
679
-
680
- * **Arguments**:
681
- * `options` (`Object`):
682
- * `options.chart` (`string`):
683
- * `options.text` (`string|Function`):
684
- * `[options.position='left']` (`'left'|'right'`):
685
- * `[options.style]` (`Object`):
686
- * **Returns**: `this` - The chainable presentation engine instance.
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. Offsets (`x`, `y`) are relative to the cell's top-left corner. Oversized shapes are scaled down proportionally to fit inside the cell.
687
176
 
688
177
  ```javascript
689
- ppt.addTextNearChartLabel({
690
- chart: 'SalesChart',
691
- text: 'Series',
692
- position: 'left'
178
+ // Add a simple indicator
179
+ await ppt.addCellShape('SalesTable', 2, 1, {
180
+ type: 'circle',
181
+ width: 12,
182
+ height: 12,
183
+ fill: '#10B981' // Green status dot
693
184
  });
694
- ```
695
-
696
- #### `updateChartData(())`
697
- Delegates core actions to slide element sub-managers.
698
185
 
699
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
700
-
701
- ```javascript
702
- ppt.useSlide(1).updateChartData('sales-chart', {
703
- categories: ['Q1', 'Q2'],
704
- series: [{ name: 'Actual', values: [100, 150] }]
186
+ // Add a badge with text and custom offsets
187
+ await ppt.addCellShape('SalesTable', 1, 2, {
188
+ type: 'badge',
189
+ text: 'Active',
190
+ fill: '#3B82F6',
191
+ x: 4,
192
+ y: 2,
193
+ width: 50,
194
+ height: 16
705
195
  });
706
196
  ```
707
197
 
708
- #### `replaceChartSeries(())`
709
- Delegates core actions to slide element sub-managers.
710
-
711
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
712
-
713
- ```javascript
714
- ppt.useSlide(1).replaceChartSeries(());
715
- ```
716
-
717
- #### `updateChartTitle(())`
718
- Delegates core actions to slide element sub-managers.
719
-
720
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
721
-
722
- ```javascript
723
- ppt.useSlide(1).updateChartTitle('sales-chart', 'Quarterly Metrics Overview');
724
- ```
725
-
726
- #### `updateChartCategories(())`
727
- Delegates core actions to slide element sub-managers.
728
-
729
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
730
-
198
+ ### XML Folder Workflow
731
199
  ```javascript
732
- ppt.useSlide(1).updateChartCategories(());
733
- ```
734
-
735
- #### `updateDataLabels(())`
736
- Delegates core actions to slide element sub-managers.
200
+ // Extract PPTX to a folder of XML files (version-control friendly)
201
+ await PPTXTemplater.extractPptx('template.pptx', './pptx-xml/');
737
202
 
738
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
739
-
740
- ```javascript
741
- ppt.useSlide(1).updateDataLabels('SalesChart', {
742
- series: 0,
743
- labels: ['Excellent', 'Good', 'Poor']
744
- });
203
+ // Load, modify, rebuild
204
+ const ppt = await PPTXTemplater.load('./pptx-xml/');
205
+ ppt.useAllSlides().replaceTextByTag('{{env}}', 'Production');
206
+ await PPTXTemplater.buildPptx('./pptx-xml/', 'output.pptx');
745
207
  ```
746
208
 
747
- #### `getDataLabels(())`
748
- Delegates core actions to slide element sub-managers.
749
-
750
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
751
-
752
- ```javascript
753
- const labels = await ppt.useSlide(1).getDataLabels('SalesChart', { series: 0 });
754
- console.log(labels); // [{ point: 0, value: 'Excellent' }, ...]
755
- ```
209
+ ---
756
210
 
757
- #### `validateDataLabels(())`
758
- Delegates core actions to slide element sub-managers.
211
+ ## API Reference
759
212
 
760
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
213
+ Full API documentation with examples, parameter types, and advanced usage:
761
214
 
762
- ```javascript
763
- const result = await ppt.useSlide(1).validateDataLabels('SalesChart', {
764
- labels: ['High', 'Low']
765
- });
766
- console.log(result.valid);
767
- ```
215
+ **👉 https://jsuyog2.github.io/node-pptx-templater/**
768
216
 
769
- #### `validateChartLabels(())`
770
- Delegates core actions to slide element sub-managers.
217
+ ---
771
218
 
772
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
219
+ ## Output Options
773
220
 
774
221
  ```javascript
775
- const result = await ppt.useSlide(1).validateChartLabels('SalesChart', {
776
- labels: ['High', 'Low']
777
- });
778
- console.log(result.valid);
222
+ await ppt.saveToFile('./output.pptx'); // File on disk
223
+ const buffer = await ppt.toBuffer(); // Node.js Buffer (for HTTP responses)
224
+ const stream = await ppt.toStream(); // Readable stream (for piping)
225
+ await ppt.saveToFolder('./output-xml/'); // Raw XML folder
779
226
  ```
780
227
 
781
- #### `validateSeriesNameLabels(())`
782
- Delegates core actions to slide element sub-managers.
228
+ ---
783
229
 
784
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
230
+ ## Caching & Performance
785
231
 
786
232
  ```javascript
787
- const result = await ppt.useSlide(1).validateSeriesNameLabels('SalesChart', {
788
- enabled: true,
789
- position: 'left'
790
- });
791
- console.log(result.valid);
792
- ```
233
+ // Preload templates for repeated generation (e.g., in a web server)
234
+ await PPTXTemplater.preload('./template.pptx');
793
235
 
794
- #### `getCharts(())`
795
- Delegates core actions to slide element sub-managers.
236
+ // Load from cache — zero disk I/O on subsequent calls
237
+ const ppt = await PPTXTemplater.fromCache('./template.pptx');
796
238
 
797
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
798
-
799
- ```javascript
800
- ppt.useSlide(1).getCharts(());
239
+ // Profile performance
240
+ ppt.enablePerformanceProfile();
241
+ // ... do work ...
242
+ console.log(ppt.getPerformanceMetrics());
801
243
  ```
802
244
 
803
245
  ---
804
246
 
805
- ### Slides API
806
-
807
- #### `useSlide(...slideRefs)`
808
- Selects one or more slides to work on. All subsequent operations (replaceText, updateChart, etc.) apply to these slides. If not called, operations apply to ALL slides.
809
-
810
- * **Arguments**:
811
- * `slideRefs` (`...number|string`): Slide numbers (1-based), IDs, or tags.
812
- * **Returns**: `PPTXTemplater` - this (chainable)
813
-
814
- ```javascript
815
- ppt.useSlide(1).useSlide(...slideRefs);
816
- ```
817
-
818
- #### `useAllSlides()`
819
- Selects all slides.
820
-
821
- * **Returns**: `PPTXTemplater` - this (chainable)
247
+ ## Validation & Repair
822
248
 
823
249
  ```javascript
824
- ppt.useSlide(1).useAllSlides();
825
- ```
826
-
827
- #### `addSlide(options = {})`
828
- Adds a new slide to the presentation. Automatically generates required XML and relationship entries.
829
-
830
- * **Arguments**:
831
- * `options` (`NewSlideOptions`): Slide definition.
832
- * `[options.title]` (`string`): Slide title text.
833
- * `[options.layout]` (`string`): Layout name to use (default: 'blank').
834
- * `[options.elements]` (`SlideElement[]`): Elements to add to the slide.
835
- * **Returns**: `PPTXTemplater` - this (chainable)
836
-
837
- ```javascript
838
- ppt.useSlide(1).addSlide(options = {});
839
- ```
840
-
841
- #### `cloneSlide(sourceSlideNumber, atPosition)`
842
- Clones an existing slide and appends it to the end (or at a position).
843
-
844
- * **Arguments**:
845
- * `sourceSlideNumber` (`number`): 1-based source slide number.
846
- * `[atPosition]` (`number`): Optional position to insert (1-based). Default: append.
847
- * **Returns**: `PPTXTemplater` - this (chainable)
848
-
849
- ```javascript
850
- ppt.useSlide(1).cloneSlide(sourceSlideNumber, atPosition);
851
- ```
852
-
853
- #### `removeSlide(slideNumber)`
854
- Removes a slide from the presentation.
855
-
856
- * **Arguments**:
857
- * `slideNumber` (`number`): 1-based slide number to remove.
858
- * **Returns**: `PPTXTemplater` - this (chainable)
859
-
860
- ```javascript
861
- ppt.useSlide(1).removeSlide(slideNumber);
862
- ```
863
-
864
- #### `reorderSlides(order)`
865
- Reorders slides in the presentation.
866
-
867
- * **Arguments**:
868
- * `order` (`number[]`): Array of 1-based slide numbers in desired order.
869
- * **Returns**: `PPTXTemplater` - this (chainable)
870
-
871
- ```javascript
872
- ppt.useSlide(1).reorderSlides(order);
873
- ```
874
-
875
- #### `tagSlide(slideNumber, tag)`
876
- Tags a slide with a custom string identifier for later selection.
877
-
878
- * **Arguments**:
879
- * `slideNumber` (`number`): 1-based slide number.
880
- * `tag` (`string`): Custom tag string.
881
- * **Returns**: `PPTXTemplater` - this (chainable)
882
-
883
- ```javascript
884
- ppt.useSlide(1).tagSlide(slideNumber, tag);
885
- ```
886
-
887
- #### `exportSlides(...slideNumbers)`
888
- Exports selected slides to a new standalone PPTX engine. Useful for creating "slide decks" from a master template.
889
-
890
- * **Arguments**:
891
- * `slideNumbers` (`...number`): 1-based slide numbers to export.
892
- * **Returns**: `Promise<PPTXTemplater>` - New engine with only the selected slides.
893
-
894
- ```javascript
895
- ppt.useSlide(1).exportSlides(...slideNumbers);
896
- ```
897
-
898
- #### `importSlideFrom(sourceEngine, slideRef)`
899
- Imports a single slide from another PPTXTemplater instance into this presentation. Preserves all slide layouts, charts, relationships, and embedded media.
900
-
901
- * **Arguments**:
902
- * `sourceEngine` (`PPTXTemplater`): Source PPTXTemplater instance.
903
- * `slideRef` (`number|string`): Slide index (1-based), ID, or custom tag.
904
- * **Returns**: `Promise<PPTXTemplater>` - this (chainable)
905
-
906
- ```javascript
907
- const source = await PPTXTemplater.load('template2.pptx');
908
- await ppt.importSlideFrom(source, 1);
909
- ```
910
-
911
- #### `importSlides(slideIndices)`
912
- Imports selected slides from the current template, discarding the rest. The remaining slides are reordered to match the provided array. Preserves all layouts, themes, relationships, and embedded media.
913
-
914
- * **Arguments**:
915
- * `slideIndices` (`number[]`): Array of 1-based slide indices to keep.
916
- * **Returns**: `PPTXTemplater` - this (chainable)
917
-
918
- ```javascript
919
- ppt.useSlide(1).importSlides(slideIndices);
920
- ```
921
-
922
- #### `duplicateSlide(())`
923
- Delegates core actions to slide element sub-managers.
924
-
925
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
926
-
927
- ```javascript
928
- ppt.duplicateSlide(1, 2);
929
- ```
930
-
931
- #### `deleteSlide(())`
932
- Delegates core actions to slide element sub-managers.
933
-
934
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
935
-
936
- ```javascript
937
- ppt.useSlide(1).deleteSlide(());
938
- ```
939
-
940
- #### `moveSlide(())`
941
- Delegates core actions to slide element sub-managers.
942
-
943
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
944
-
945
- ```javascript
946
- ppt.useSlide(1).moveSlide(());
947
- ```
948
-
949
- #### `insertSlide(())`
950
- Delegates core actions to slide element sub-managers.
951
-
952
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
953
-
954
- ```javascript
955
- ppt.useSlide(1).insertSlide(());
956
- ```
957
-
958
- #### `getSlides(())`
959
- Delegates core actions to slide element sub-managers.
960
-
961
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
962
-
963
- ```javascript
964
- ppt.useSlide(1).getSlides(());
965
- ```
966
-
967
- ---
968
-
969
- ### Text API
970
-
971
- #### `replaceText(replacements)`
972
- Replaces template placeholders (e.g., {{key}}) with values in the selected slides. Works inside text boxes, titles, grouped shapes, tables, and shapes.
973
-
974
- * **Arguments**:
975
- * `replacements` (`Object.<string, string>`): Map of placeholder → replacement value.
976
- * **Returns**: `PPTXTemplater` - this (chainable)
977
-
978
- ```javascript
979
- ppt.useSlide(1).replaceText(replacements);
980
- ```
981
-
982
- #### `addHyperlink(options)`
983
- Adds or replaces a hyperlink on a text run or shape.
984
-
985
- * **Arguments**:
986
- * `options` (`HyperlinkOptions`): Hyperlink configuration.
987
- * `options.text` (`string`): Text to find and make clickable.
988
- * `options.url` (`string`): Target URL.
989
- * `[options.tooltip]` (`string`): Optional tooltip.
990
- * **Returns**: `PPTXTemplater` - this (chainable)
991
-
992
- ```javascript
993
- ppt.useSlide(1).addHyperlink(options);
994
- ```
995
-
996
- #### `addSlideLink(options)`
997
- Adds an inter-slide hyperlink to a specific text element.
998
-
999
- * **Arguments**:
1000
- * `options` (`Object`): Link configuration.
1001
- * `options.sourceSlide` (`number`): Source slide number (1-based).
1002
- * `options.targetSlide` (`number`): Destination slide number (1-based).
1003
- * `options.element` (`string`): Text element to make clickable.
1004
- * **Returns**: `PPTXTemplater` - this (chainable)
1005
-
1006
- ```javascript
1007
- ppt.useSlide(1).addSlideLink(options);
1008
- ```
1009
-
1010
- #### `addImageLink(options)`
1011
- Adds an inter-slide hyperlink to an image.
1012
-
1013
- * **Arguments**:
1014
- * `options` (`Object`):
1015
- * `options.slide` (`number`): Source slide number.
1016
- * `options.imageId` (`string`): Image name/id to make clickable.
1017
- * `options.targetSlide` (`number`): Destination slide number.
1018
- * **Returns**: `PPTXTemplater` - this
1019
-
1020
- ```javascript
1021
- ppt.useSlide(1).addImageLink(options);
1022
- ```
1023
-
1024
- #### `addShapeLink(options)`
1025
- Adds an inter-slide hyperlink to a shape.
1026
-
1027
- * **Arguments**:
1028
- * `options` (`Object`):
1029
- * `options.slide` (`number`): Source slide number.
1030
- * `options.shapeId` (`string`): Shape name/id to make clickable.
1031
- * `options.targetSlide` (`number`): Destination slide number.
1032
- * **Returns**: `PPTXTemplater` - this
1033
-
1034
- ```javascript
1035
- ppt.useSlide(1).addShapeLink(options);
1036
- ```
1037
-
1038
- #### `addTextNavigationLink(options)`
1039
- Adds a special navigation link (next, previous, first, last slide) to a text element.
1040
-
1041
- * **Arguments**:
1042
- * `options` (`Object`):
1043
- * `options.slide` (`number`): Source slide number (1-based).
1044
- * `options.element` (`string`): Text element to make clickable.
1045
- * `options.action` (`'next'|'previous'|'first'|'last'`): Navigation action type.
1046
- * **Returns**: `PPTXTemplater` - this (chainable)
1047
-
1048
- ```javascript
1049
- ppt.useSlide(1).addTextNavigationLink(options);
1050
- ```
1051
-
1052
- #### `addShapeNavigationLink(options)`
1053
- Adds a special navigation link (next, previous, first, last slide) to a shape or image.
1054
-
1055
- * **Arguments**:
1056
- * `options` (`Object`):
1057
- * `options.slide` (`number`): Source slide number (1-based).
1058
- * `options.shapeId` (`string`): Shape name/id to make clickable.
1059
- * `options.action` (`'next'|'previous'|'first'|'last'`): Navigation action type.
1060
- * **Returns**: `PPTXTemplater` - this (chainable)
1061
-
1062
- ```javascript
1063
- ppt.useSlide(1).addShapeNavigationLink(options);
1064
- ```
1065
-
1066
- #### `updateText(tag, data)`
1067
- Updates shape text or list content by placeholder tag or shape name/ID. Supports bullet lists, numbered lists, nested lists, and custom styling.
1068
-
1069
- * **Arguments**:
1070
- * `tag` (`string`): Placeholder tag (e.g. '{{name}}' or 'name') or shape name/ID.
1071
- * `data` (`string|Object`): String value or list configuration object.
1072
- * **Returns**: `PPTXTemplater` - this (chainable)
1073
-
1074
- ```javascript
1075
- ppt.useSlide(1).updateText('Features', {
1076
- list: ['Point A', 'Point B', 'Point C']
1077
- });
1078
- ```
1079
-
1080
- #### `getList(tag)`
1081
- Retrieves list items from a shape or text box by name or placeholder tag.
1082
-
1083
- * **Arguments**:
1084
- * `tag` (`string`): Shape name/ID or placeholder tag.
1085
- * **Returns**: `Array` - Nested list structure of items.
1086
-
1087
- ```javascript
1088
- const items = ppt.useSlide(1).getList('Features');
1089
- console.log(items); // ['A', { text: 'B', children: [...] }]
1090
- ```
1091
-
1092
- #### `validateList(data)`
1093
- Validates a list structure and values.
1094
-
1095
- * **Arguments**:
1096
- * `data` (`Object|Array`): List config object or array of items.
1097
- * **Returns**: `Object` - Report containing validation result.
1098
-
1099
- ```javascript
1100
- const result = ppt.validateList(['Valid string', 'Another item']);
1101
- console.log(result.valid);
1102
- ```
1103
-
1104
- #### `replaceTextByTag(())`
1105
- Delegates core actions to slide element sub-managers.
1106
-
1107
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1108
-
1109
- ```javascript
1110
- ppt.useSlide(1).replaceTextByTag('company', 'Acme Corp');
1111
- ```
1112
-
1113
- #### `replaceMultiple(())`
1114
- Delegates core actions to slide element sub-managers.
1115
-
1116
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1117
-
1118
- ```javascript
1119
- ppt.useSlide(1).replaceMultiple(());
1120
- ```
1121
-
1122
- #### `findText(())`
1123
- Delegates core actions to slide element sub-managers.
1124
-
1125
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1126
-
1127
- ```javascript
1128
- ppt.useSlide(1).findText(());
1129
- ```
1130
-
1131
- #### `getTextElements(())`
1132
- Delegates core actions to slide element sub-managers.
1133
-
1134
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1135
-
1136
- ```javascript
1137
- ppt.useSlide(1).getTextElements(());
1138
- ```
1139
-
1140
- ---
1141
-
1142
- ### Images API
1143
-
1144
- #### `replaceImage(())`
1145
- Delegates core actions to slide element sub-managers.
1146
-
1147
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1148
-
1149
- ```javascript
1150
- await ppt.useSlide(1).replaceImage('logo-img', './new-logo.png');
1151
- ```
1152
-
1153
- #### `addImage(())`
1154
- Delegates core actions to slide element sub-managers.
1155
-
1156
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1157
-
1158
- ```javascript
1159
- ppt.useSlide(1).addImage(());
1160
- ```
1161
-
1162
- #### `removeImage(())`
1163
- Delegates core actions to slide element sub-managers.
1164
-
1165
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1166
-
1167
- ```javascript
1168
- ppt.useSlide(1).removeImage(());
1169
- ```
1170
-
1171
- #### `getImages(())`
1172
- Delegates core actions to slide element sub-managers.
1173
-
1174
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1175
-
1176
- ```javascript
1177
- ppt.useSlide(1).getImages(());
1178
- ```
1179
-
1180
- ---
1181
-
1182
- ### Shapes API
1183
-
1184
- #### `updateShapePosition(shapeId, options = {})`
1185
- Updates the position and/or dimensions of an existing shape on targeted slides.
1186
-
1187
- * **Arguments**:
1188
- * `shapeId` (`string`):
1189
- * `options` (`Object`):
1190
- * `[options.x]` (`number`):
1191
- * `[options.y]` (`number`):
1192
- * `[options.width]` (`number`):
1193
- * `[options.height]` (`number`):
1194
- * **Returns**: `this` - The chainable presentation engine instance.
1195
-
1196
- ```javascript
1197
- ppt.useSlide(1).updateShapePosition('TitleShape', { x: 1000000, y: 1500000 });
1198
- ```
1199
-
1200
- #### `updateTextBoxPosition(textBoxId, options = {})`
1201
- Updates the position and/or dimensions of an existing textbox on targeted slides.
1202
-
1203
- * **Arguments**:
1204
- * `textBoxId` (`string`):
1205
- * `options` (`Object`):
1206
- * `[options.x]` (`number`):
1207
- * `[options.y]` (`number`):
1208
- * `[options.width]` (`number`):
1209
- * `[options.height]` (`number`):
1210
- * **Returns**: `this` - The chainable presentation engine instance.
1211
-
1212
- ```javascript
1213
- ppt.useSlide(1).updateTextBoxPosition('TextBox 2', { x: 1000000, y: 1500000 });
1214
- ```
1215
-
1216
- #### `validateShape(options)`
1217
- Validates shape options configuration.
1218
-
1219
- * **Arguments**:
1220
- * `options` (`Object`):
1221
- * **Returns**: `string[]` - List of validation error messages.
1222
-
1223
- ```javascript
1224
- const errors = ppt.validateShape(shapeOptions);
1225
- ```
1226
-
1227
- #### `addShape(options)`
1228
- Adds a new shape dynamically to the targeted slide(s).
1229
-
1230
- * **Arguments**:
1231
- * `options` (`Object`):
1232
- * **Returns**: `this` - The chainable presentation templater instance.
1233
-
1234
- ```javascript
1235
- await ppt.useSlide(1).addShape({
1236
- type: 'rectangle',
1237
- id: 'sales-box',
1238
- x: 100,
1239
- y: 100,
1240
- width: 200,
1241
- height: 100,
1242
- fill: '#2563EB'
1243
- });
1244
- ```
1245
-
1246
- #### `updateShape(shapeId, options)`
1247
- Updates an existing shape in-place.
1248
-
1249
- * **Arguments**:
1250
- * `shapeId` (`string`):
1251
- * `options` (`Object`):
1252
- * **Returns**: `this` - The chainable presentation templater instance.
1253
-
1254
- ```javascript
1255
- await ppt.useSlide(1).updateShape('sales-box', { fill: '#10B981' });
1256
- ```
1257
-
1258
- #### `removeShape(shapeId)`
1259
- Removes a shape from the targeted slide(s).
1260
-
1261
- * **Arguments**:
1262
- * `shapeId` (`string`):
1263
- * **Returns**: `this` - The chainable presentation templater instance.
1264
-
1265
- ```javascript
1266
- await ppt.useSlide(1).removeShape('sales-box');
1267
- ```
1268
-
1269
- #### `getShape(shapeId)`
1270
- Discovers and retrieves details of an existing shape on the targeted slides.
1271
-
1272
- * **Arguments**:
1273
- * `shapeId` (`string`):
1274
- * **Returns**: `Object|null` - Shape details object, or null if not found.
1275
-
1276
- ```javascript
1277
- const shape = ppt.getShape('sales-box');
1278
- ```
1279
-
1280
- #### `updateShapeText(())`
1281
- Delegates core actions to slide element sub-managers.
1282
-
1283
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1284
-
1285
- ```javascript
1286
- ppt.useSlide(1).updateShapeText(());
1287
- ```
1288
-
1289
- #### `cloneShape(())`
1290
- Delegates core actions to slide element sub-managers.
1291
-
1292
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1293
-
1294
- ```javascript
1295
- ppt.useSlide(1).cloneShape('card-bg', 'card-bg-2');
1296
- ```
1297
-
1298
- #### `deleteShape(())`
1299
- Delegates core actions to slide element sub-managers.
1300
-
1301
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1302
-
1303
- ```javascript
1304
- ppt.useSlide(1).deleteShape(());
1305
- ```
1306
-
1307
- #### `getShapes(())`
1308
- Delegates core actions to slide element sub-managers.
1309
-
1310
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1311
-
1312
- ```javascript
1313
- ppt.useSlide(1).getShapes(());
1314
- ```
1315
-
1316
- ---
1317
-
1318
- ### Layer Stacking (Z-Order)
1319
-
1320
- #### `bringForward(optionsOrId)`
1321
- Moves slide element one layer forward.
1322
-
1323
-
1324
- ```javascript
1325
- ppt.useSlide(1).bringForward(optionsOrId);
1326
- ```
1327
-
1328
- #### `sendBackward(optionsOrId)`
1329
- Moves slide element one layer backward.
1330
-
1331
-
1332
- ```javascript
1333
- ppt.useSlide(1).sendBackward(optionsOrId);
1334
- ```
1335
-
1336
- #### `bringToFront(optionsOrId)`
1337
- Moves slide element above all other objects.
1338
-
1339
-
1340
- ```javascript
1341
- ppt.useSlide(1).bringToFront('OverlayLogo');
1342
- ```
1343
-
1344
- #### `sendToBack(optionsOrId)`
1345
- Moves slide element behind all other objects.
1346
-
1347
-
1348
- ```javascript
1349
- ppt.useSlide(1).sendToBack(optionsOrId);
1350
- ```
1351
-
1352
- #### `setZIndex(optionsOrId, zIndex)`
1353
- Moves slide element to the specific 1-based stacking position.
1354
-
1355
-
1356
- ```javascript
1357
- ppt.useSlide(1).setZIndex(optionsOrId, zIndex);
1358
- ```
1359
-
1360
- #### `moveObjectBefore(optionsOrId, targetId)`
1361
- Moves slide element directly before (below) a target element.
1362
-
1363
-
1364
- ```javascript
1365
- ppt.useSlide(1).moveObjectBefore(optionsOrId, targetId);
1366
- ```
1367
-
1368
- #### `moveObjectAfter(optionsOrId, targetId)`
1369
- Moves slide element directly after (above) a target element.
1370
-
1371
-
1372
- ```javascript
1373
- ppt.useSlide(1).moveObjectAfter(optionsOrId, targetId);
1374
- ```
1375
-
1376
- #### `reorderObjects(optionsOrOrder)`
1377
- Reorders slide objects exactly as specified in the array.
1378
-
1379
-
1380
- ```javascript
1381
- ppt.useSlide(1).reorderObjects(optionsOrOrder);
1382
- ```
1383
-
1384
- #### `getObjectOrder(slideIndex)`
1385
- Gets the ordered metadata of all objects on the slide.
1386
-
1387
-
1388
- ```javascript
1389
- ppt.useSlide(1).getObjectOrder(slideIndex);
1390
- ```
1391
-
1392
- #### `applyZOrder(slideOrConfigs, configsOption)`
1393
- Applies bulk template configurations for slide elements stacking layers.
1394
-
1395
-
1396
- ```javascript
1397
- ppt.useSlide(1).applyZOrder(slideOrConfigs, configsOption);
1398
- ```
1399
-
1400
- #### `getTopMostObject(slideIndex)`
1401
- Retrieves the info of the top-most object on the slide.
1402
-
1403
-
1404
- ```javascript
1405
- ppt.useSlide(1).getTopMostObject(slideIndex);
1406
- ```
1407
-
1408
- #### `getBottomMostObject(slideIndex)`
1409
- Retrieves the info of the bottom-most object on the slide.
1410
-
1411
-
1412
- ```javascript
1413
- ppt.useSlide(1).getBottomMostObject(slideIndex);
1414
- ```
1415
-
1416
- #### `swapObjects(slideIndexOrId1, id1OrId2, id2)`
1417
- Swaps stacking positions of two slide objects.
1418
-
1419
-
1420
- ```javascript
1421
- ppt.useSlide(1).swapObjects(slideIndexOrId1, id1OrId2, id2);
1422
- ```
1423
-
1424
- #### `sortObjects(slideIndexOrCompareFn, compareFnOption)`
1425
- Sorts stacking order using a custom comparison function.
1426
-
1427
-
1428
- ```javascript
1429
- ppt.useSlide(1).sortObjects(slideIndexOrCompareFn, compareFnOption);
1430
- ```
1431
-
1432
- #### `normalizeZOrder(slideIndex)`
1433
- Cleans up and normalizes stacking order consistency.
1434
-
1435
-
1436
- ```javascript
1437
- ppt.useSlide(1).normalizeZOrder(slideIndex);
1438
- ```
1439
-
1440
- ---
1441
-
1442
- ### Utilities & Validation
1443
-
1444
- #### `const()`
1445
- This is the primary public API. It coordinates all sub-managers (ZipManager, SlideManager, ChartManager, etc.) and exposes a fluent, chainable interface for template manipulation. OpenXML PPTX Structure: ├── [Content_Types].xml — lists all parts and their MIME types ├── _rels/.rels — root relationships (points to presentation) ├── ppt/ │ ├── presentation.xml — slide order, slide masters references │ ├── _rels/presentation.xml.rels │ ├── slides/ │ │ ├── slide1.xml — individual slide content │ │ └── _rels/slide1.xml.rels │ ├── slideLayouts/ — layout templates (title, content, etc.) │ ├── slideMasters/ — master slide designs │ ├── theme/ — color/font themes │ ├── charts/ — embedded chart XML │ └── media/ — embedded images/videos └── docProps/ ├── core.xml — author, title, etc. └── app.xml — application metadata
1446
-
1447
-
1448
- ```javascript
1449
- ppt.useSlide(1).const();
1450
- ```
1451
-
1452
- #### `class()`
1453
-
1454
-
1455
-
1456
- ```javascript
1457
- ppt.useSlide(1).class();
1458
- ```
1459
-
1460
- #### `static()`
1461
- Loads a PPTX template from a file path or buffer. @static @throws {PPTXError} If the file cannot be read or is not a valid PPTX.
1462
-
1463
- * **Arguments**:
1464
- * `source` (`string|Buffer`): Path to PPTX file or Buffer containing PPTX data.
1465
- * **Returns**: `Promise<PPTXTemplater>` - Initialized engine instance.
1466
-
1467
- ```javascript
1468
- ppt.useSlide(1).static();
1469
- ```
1470
-
1471
- #### `getInfo()`
1472
- Returns presentation metadata (title, author, slide count, etc.)
1473
-
1474
- * **Returns**: `PresentationInfo` - Metadata object.
1475
-
1476
- ```javascript
1477
- ppt.useSlide(1).getInfo();
1478
- ```
1479
-
1480
- #### `validate()`
1481
- Validates the XML structure of the current PPTX. Reports issues with relationship IDs, missing parts, etc.
1482
-
1483
- * **Returns**: `ValidationResult` - Object with `valid`, `errors`, and `warnings` arrays.
1484
-
1485
- ```javascript
1486
- ppt.useSlide(1).validate();
1487
- ```
1488
-
1489
- #### `repair()`
1490
- Repairs corrupted OpenXML structure, relationships, and content types. Removes orphan relationships, rebuilds slide references, and fixes missing entries.
1491
-
1492
- * **Returns**: `Promise<PPTXTemplater>` - this (chainable)
1493
-
1494
- ```javascript
1495
- ppt.useSlide(1).repair();
1496
- ```
1497
-
1498
- #### `debugRelationships()`
1499
- Logs all relationships across the presentation to the console for debugging.
1500
-
1501
- * **Returns**: `PPTXTemplater` - this (chainable)
1502
-
1503
- ```javascript
1504
- ppt.useSlide(1).debugRelationships();
1505
- ```
1506
-
1507
- #### `inspectSlide(slideIndex)`
1508
- Inspects a specific slide's structure and relationships.
1509
-
1510
- * **Arguments**:
1511
- * `slideIndex` (`number`): 1-based slide index.
1512
- * **Returns**: `PPTXTemplater` - this (chainable)
1513
-
1514
- ```javascript
1515
- ppt.useSlide(1).inspectSlide(slideIndex);
1516
- ```
1517
-
1518
- #### `inspectXML(xmlPath)`
1519
- Inspects and logs the raw XML of any file in the ZIP.
1520
-
1521
- * **Arguments**:
1522
- * `xmlPath` (`string`): Path inside the ZIP (e.g., 'ppt/slides/slide1.xml')
1523
- * **Returns**: `Promise<PPTXTemplater>` - this (chainable)
1524
-
1525
- ```javascript
1526
- ppt.useSlide(1).inspectXML(xmlPath);
1527
- ```
1528
-
1529
- #### `inspectChart(chartId)`
1530
- Inspects a specific chart's metadata and structure.
1531
-
1532
- * **Arguments**:
1533
- * `chartId` (`string`):
1534
-
1535
- ```javascript
1536
- ppt.useSlide(1).inspectChart(chartId);
1537
- ```
1538
-
1539
- #### `inspectChartXML(chartFileName)`
1540
- Inspects and logs the raw XML of a chart file.
1541
-
1542
- * **Arguments**:
1543
- * `chartFileName` (`string`):
1544
-
1545
- ```javascript
1546
- ppt.useSlide(1).inspectChartXML(chartFileName);
1547
- ```
1548
-
1549
- #### `debugChartRelationships()`
1550
- Logs all chart relationships.
1551
-
1552
-
1553
- ```javascript
1554
- ppt.useSlide(1).debugChartRelationships();
1555
- ```
1556
-
1557
- #### `saveToFile(filePath, options = {})`
1558
- Saves the modified PPTX to a file on disk.
1559
-
1560
- * **Arguments**:
1561
- * `filePath` (`string`): Output file path.
1562
- * `[options]` (`Object`): Save options.
1563
- * `[options.strict=false]` (`boolean`): Throw error on validation failure.
1564
- * **Returns**: `Promise<void>` -
1565
-
1566
- ```javascript
1567
- ppt.useSlide(1).saveToFile(filePath, options = {});
1568
- ```
1569
-
1570
- #### `save(filePath, options = {})`
1571
- Saves the presentation. Equivalent to saveToFile.
1572
-
1573
- * **Arguments**:
1574
- * `filePath` (`string`): Output file path.
1575
- * `[options]` (`Object`): Save options.
1576
- * **Returns**: `Promise<void>` -
1577
-
1578
- ```javascript
1579
- await ppt.save('output.pptx');
1580
- ```
1581
-
1582
- #### `saveXml(folderPath)`
1583
- Saves the modified presentation XML structures directly to a folder.
1584
-
1585
- * **Arguments**:
1586
- * `folderPath` (`string`): Target directory path.
1587
- * **Returns**: `Promise<void>` -
1588
-
1589
- ```javascript
1590
- ppt.useSlide(1).saveXml(folderPath);
1591
- ```
1592
-
1593
- #### `saveToFolder(folderPath)`
1594
- Saves the modified presentation XML structures directly to a folder.
1595
-
1596
- * **Arguments**:
1597
- * `folderPath` (`string`): Target directory path.
1598
- * **Returns**: `Promise<void>` -
1599
-
1600
- ```javascript
1601
- await ppt.saveToFolder('./output-template');
1602
- ```
1603
-
1604
- #### `toBuffer(options = {})`
1605
- Returns the PPTX content as a Node.js Buffer.
1606
-
1607
- * **Arguments**:
1608
- * `[options]` (`Object`): Save options.
1609
- * **Returns**: `Promise<Buffer>` -
1610
-
1611
- ```javascript
1612
- ppt.useSlide(1).toBuffer(options = {});
1613
- ```
1614
-
1615
- #### `toStream(options = {})`
1616
- Returns the PPTX content as a readable Node.js Stream.
1617
-
1618
- * **Arguments**:
1619
- * `[options]` (`Object`): Save options.
1620
- * **Returns**: `Promise<NodeJS.ReadableStream>` -
1621
-
1622
- ```javascript
1623
- ppt.useSlide(1).toStream(options = {});
1624
- ```
1625
-
1626
- #### `saveToStream(writableOrOptions, options = {})`
1627
- Saves the presentation to a readable stream or pipes it to a writable stream.
1628
-
1629
- * **Arguments**:
1630
- * `[writableOrOptions]` (`NodeJS.WritableStream|Object`): Writable stream to pipe to, or options object.
1631
- * `[options]` (`Object`): Save options if writable stream was passed first.
1632
- * **Returns**: `Promise<NodeJS.ReadableStream|void>` -
1633
-
1634
- ```javascript
1635
- ppt.useSlide(1).saveToStream(writableOrOptions, options = {});
1636
- ```
1637
-
1638
- #### `validatePresentationXml()`
1639
- Performs validation specifically on PowerPoint XML folder contents/relationships.
1640
-
1641
- * **Returns**: `Promise<{valid: boolean, errors: string[], warnings: string[]` -
1642
-
1643
- ```javascript
1644
- const report = await ppt.validatePresentationXml();
1645
- if (!report.valid) console.error(report.errors);
1646
- ```
1647
-
1648
- #### `slideCount()`
1649
- Returns the total number of slides in the loaded presentation. @type {number}
1650
-
1651
-
1652
- ```javascript
1653
- ppt.useSlide(1).slideCount();
1654
- ```
1655
-
1656
- #### `function()`
1657
- OpenXML relationship IDs follow the format rId1, rId2, rId3, ... They must be unique within each .rels file. These utilities generate collision-free IDs when adding new relationships. / /** Generates the next available relationship ID given an array of existing IDs. Always uses the format "rId{N}" where N is the next integer after the max.
1658
-
1659
- * **Arguments**:
1660
- * `existingIds` (`string[]`): Array of existing rId strings (e.g., ['rId1', 'rId2']).
1661
- * **Returns**: `string` - New relationship ID (e.g., 'rId3').
1662
-
1663
- ```javascript
1664
- ppt.useSlide(1).function();
1665
- ```
1666
-
1667
- #### `preload(())`
1668
- Delegates core actions to slide element sub-managers.
1669
-
1670
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1671
-
1672
- ```javascript
1673
- ppt.useSlide(1).preload(());
1674
- ```
1675
-
1676
- #### `cache(())`
1677
- Delegates core actions to slide element sub-managers.
1678
-
1679
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1680
-
1681
- ```javascript
1682
- ppt.useSlide(1).cache(());
1683
- ```
1684
-
1685
- #### `fromCache(())`
1686
- Delegates core actions to slide element sub-managers.
1687
-
1688
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1689
-
1690
- ```javascript
1691
- ppt.useSlide(1).fromCache(());
1692
- ```
1693
-
1694
- #### `clearCache(())`
1695
- Delegates core actions to slide element sub-managers.
1696
-
1697
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1698
-
1699
- ```javascript
1700
- ppt.useSlide(1).clearCache(());
1701
- ```
1702
-
1703
- #### `enablePerformanceProfile(())`
1704
- Delegates core actions to slide element sub-managers.
1705
-
1706
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1707
-
1708
- ```javascript
1709
- ppt.useSlide(1).enablePerformanceProfile(());
1710
- ```
1711
-
1712
- #### `getPerformanceMetrics(())`
1713
- Delegates core actions to slide element sub-managers.
1714
-
1715
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1716
-
1717
- ```javascript
1718
- ppt.useSlide(1).getPerformanceMetrics(());
1719
- ```
1720
-
1721
- #### `fromPresentationXml(())`
1722
- Delegates core actions to slide element sub-managers.
1723
-
1724
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1725
-
1726
- ```javascript
1727
- const ppt = await PPTXTemplate.fromPresentationXml('./template-folder');
1728
- ```
1729
-
1730
- #### `extractPptx(())`
1731
- Delegates core actions to slide element sub-managers.
1732
-
1733
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1734
-
1735
- ```javascript
1736
- await PPTXTemplater.extractPptx('sample.pptx', './extracted');
1737
- ```
1738
-
1739
- #### `buildPptx(())`
1740
- Delegates core actions to slide element sub-managers.
1741
-
1742
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1743
-
1744
- ```javascript
1745
- await PPTXTemplater.buildPptx('./extracted', 'output.pptx');
1746
- ```
1747
-
1748
- #### `validatePresentation(())`
1749
- Delegates core actions to slide element sub-managers.
1750
-
1751
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1752
-
1753
- ```javascript
1754
- ppt.useSlide(1).validatePresentation(());
1755
- ```
1756
-
1757
- #### `validateSlide(())`
1758
- Delegates core actions to slide element sub-managers.
1759
-
1760
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1761
-
1762
- ```javascript
1763
- ppt.useSlide(1).validateSlide(());
1764
- ```
1765
-
1766
- #### `validateTable(())`
1767
- Delegates core actions to slide element sub-managers.
1768
-
1769
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1770
-
1771
- ```javascript
1772
- ppt.useSlide(1).validateTable(());
1773
- ```
1774
-
1775
- #### `validateArchive(())`
1776
- Delegates core actions to slide element sub-managers.
1777
-
1778
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1779
-
1780
- ```javascript
1781
- ppt.useSlide(1).validateArchive(());
1782
- ```
1783
-
1784
- #### `enableDebugZip(())`
1785
- Delegates core actions to slide element sub-managers.
1786
-
1787
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1788
-
1789
- ```javascript
1790
- ppt.useSlide(1).enableDebugZip(());
1791
- ```
1792
-
1793
- #### `validateRelationships(())`
1794
- Delegates core actions to slide element sub-managers.
1795
-
1796
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1797
-
1798
- ```javascript
1799
- ppt.useSlide(1).validateRelationships(());
1800
- ```
1801
-
1802
- #### `zipManager(())`
1803
- Delegates core actions to slide element sub-managers.
1804
-
1805
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1806
-
1807
- ```javascript
1808
- ppt.useSlide(1).zipManager(());
1809
- ```
1810
-
1811
- #### `xmlParser(())`
1812
- Delegates core actions to slide element sub-managers.
1813
-
1814
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1815
-
1816
- ```javascript
1817
- ppt.useSlide(1).xmlParser(());
1818
- ```
1819
-
1820
- #### `contentTypesManager(())`
1821
- Delegates core actions to slide element sub-managers.
1822
-
1823
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1824
-
1825
- ```javascript
1826
- ppt.useSlide(1).contentTypesManager(());
1827
- ```
1828
-
1829
- #### `relationshipManager(())`
1830
- Delegates core actions to slide element sub-managers.
1831
-
1832
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1833
-
1834
- ```javascript
1835
- ppt.useSlide(1).relationshipManager(());
1836
- ```
1837
-
1838
- #### `slideManager(())`
1839
- Delegates core actions to slide element sub-managers.
1840
-
1841
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1842
-
1843
- ```javascript
1844
- ppt.useSlide(1).slideManager(());
1845
- ```
1846
-
1847
- #### `chartManager(())`
1848
- Delegates core actions to slide element sub-managers.
1849
-
1850
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1851
-
1852
- ```javascript
1853
- ppt.useSlide(1).chartManager(());
1854
- ```
1855
-
1856
- #### `tableManager(())`
1857
- Delegates core actions to slide element sub-managers.
1858
-
1859
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1860
-
1861
- ```javascript
1862
- ppt.useSlide(1).tableManager(());
1863
- ```
1864
-
1865
- #### `shapeManager(())`
1866
- Delegates core actions to slide element sub-managers.
1867
-
1868
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1869
-
1870
- ```javascript
1871
- ppt.useSlide(1).shapeManager(());
1872
- ```
1873
-
1874
- #### `imageManager(())`
1875
- Delegates core actions to slide element sub-managers.
1876
-
1877
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1878
-
1879
- ```javascript
1880
- ppt.useSlide(1).imageManager(());
1881
- ```
1882
-
1883
- #### `textManager(())`
1884
- Delegates core actions to slide element sub-managers.
1885
-
1886
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1887
-
1888
- ```javascript
1889
- ppt.useSlide(1).textManager(());
1890
- ```
1891
-
1892
- #### `hyperlinkManager(())`
1893
- Delegates core actions to slide element sub-managers.
1894
-
1895
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1896
-
1897
- ```javascript
1898
- ppt.useSlide(1).hyperlinkManager(());
1899
- ```
1900
-
1901
- #### `mediaManager(())`
1902
- Delegates core actions to slide element sub-managers.
1903
-
1904
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1905
-
1906
- ```javascript
1907
- ppt.useSlide(1).mediaManager(());
1908
- ```
1909
-
1910
- #### `load(())`
1911
- Delegates core actions to slide element sub-managers.
1912
-
1913
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1914
-
1915
- ```javascript
1916
- const ppt = await PPTXTemplater.load('./my_template.pptx');
1917
- ```
1918
-
1919
- #### `create(())`
1920
- Delegates core actions to slide element sub-managers.
1921
-
1922
- * **Returns**: `PPTXTemplater` - The fluent engine instance.
1923
-
1924
- ```javascript
1925
- ppt.useSlide(1).create(());
1926
- ```
1927
-
1928
- ---
1929
-
1930
- <!-- API_REFERENCE_END -->
1931
-
1932
- ---
1933
-
1934
- ## 📊 Chart Data Labels & Value From Cells
1935
-
1936
- PPTXForge supports advanced, PowerPoint-compatible chart data labels. You can customize label data sources, templates, positioning, and visual styles.
1937
-
1938
- ### 1. Value From Cells (Excel Synchronization)
1939
- Pull dynamic data labels directly from worksheet range cells inside the backing Excel spreadsheet. This is Excel's native "Value From Cells" feature, reconstructed programmatically inside the `.pptx` XML and `.xlsx` worksheets.
1940
-
1941
- ```javascript
1942
- ppt.useSlide(1).updateDataLabels('SalesChart', {
1943
- series: 0,
1944
- labelsFromCells: 'Sheet1!D2:D5'
1945
- });
1946
- ```
1947
-
1948
- ### 2. Literal Arrays
1949
- Override data labels for specific points in a series with a static list of strings:
1950
-
1951
- ```javascript
1952
- ppt.useSlide(1).updateDataLabels('SalesChart', {
1953
- series: 0,
1954
- labels: ['Top Performance', 'Met Target', 'Action Required', 'At Risk']
1955
- });
1956
- ```
1957
-
1958
- ### 3. Dynamic Label Templates
1959
- Combine values, category names, percentages, and custom label strings to format annotations:
1960
-
1961
- ```javascript
1962
- ppt.useSlide(1).updateDataLabels('SalesChart', {
1963
- series: 0,
1964
- template: '{category}: {value} ({percentage}%)'
1965
- });
1966
- ```
1967
- * **Variables**: `{category}`, `{value}`, `{percentage}`, `{series}`, `{customLabel}`
1968
-
1969
- ### 4. Label Positions
1970
- Set label alignment to any of PowerPoint's standard values:
1971
-
1972
- ```javascript
1973
- ppt.useSlide(1).updateDataLabels('SalesChart', {
1974
- series: 0,
1975
- position: 'insideEnd' // 'center', 'insideEnd', 'insideBase', 'outsideEnd', 'bestFit', 'left', 'right', 'top', 'bottom'
1976
- });
1977
- ```
1978
-
1979
- ### 5. Custom Label Styling
1980
- Format your data labels using custom fonts, sizes, colors, and weight properties:
1981
-
1982
- ```javascript
1983
- ppt.useSlide(1).updateDataLabels('SalesChart', {
1984
- series: 0,
1985
- labels: ['High', 'Medium', 'Low'],
1986
- labelStyle: {
1987
- fontFamily: 'Century Gothic',
1988
- fontSize: 12,
1989
- color: '#0055A5',
1990
- bold: true,
1991
- italic: true,
1992
- underline: true
1993
- }
1994
- });
1995
- ```
1996
-
1997
- ### 6. Inline Custom Data Labels (`updateChart`)
1998
- You can define custom data labels inline within the standard `updateChart()` series `values` array using objects in the format `{ data: number, label: string }`. This avoids calling separate styling or update methods:
1999
-
2000
- ```javascript
2001
- ppt.useSlide(1).updateChart('RevenueChart', {
2002
- categories: ['Q1', 'Q2', 'Q3', 'Q4'],
2003
- series: [
2004
- {
2005
- name: 'Product A',
2006
- values: [
2007
- { data: 145, label: 'Q1: 145 (Low)' },
2008
- { data: 210, label: 'Q2: 210 (Med)' },
2009
- { data: 190, label: 'Q3: 190 (Med)' },
2010
- { data: 250, label: 'Q4: 250 (High)' }
2011
- ]
2012
- }
2013
- ]
2014
- });
2015
- ```
2016
-
2017
- To preserve PowerPoint integrity, the engine ensures that if one value contains a label, all values in that series must have labels, and the label properties must be string values.
2018
-
2019
- ### 7. Label Style Inheritance & Series Names Inside Bars
2020
-
2021
- #### Style Inheritance
2022
- When custom labels (inline or via `updateDataLabels`) are generated, they inherit the styling properties (font family, font size, bold, italic, color, and alignment) defined in the template's `<c:txPr>` tag for the series. This ensures your custom labels match the branding and layout design from your PowerPoint template file.
2023
-
2024
- #### Series Names Inside Bars (`showSeriesNameInBar`)
2025
- For stacked bar charts, you can show the series name inside each segment (typically centered) to make them easily readable. To enable this, set `showSeriesNameInBar: true` in the chart options (globally) or on individual series:
2026
-
2027
- ```javascript
2028
- ppt.useSlide(1).updateChart('RevenueChart', {
2029
- showSeriesNameInBar: true, // Show series name labels globally
2030
- categories: ['Q1', 'Q2', 'Q3', 'Q4'],
2031
- series: [
2032
- { name: 'Product A', values: [100, 200, 300, 400] },
2033
- { name: 'Product B', values: [150, 250, 350, 450], showSeriesNameInBar: true } // Or per-series
2034
- ]
2035
- });
2036
- ```
2037
-
2038
- #### Chart Labels Validation
2039
- You can programmatically validate that the chart labels configured in a chart conform to your template structure:
2040
-
2041
- ```javascript
2042
- const report = await ppt.useSlide(1).validateChartLabels('RevenueChart', {
2043
- labels: ['Custom label 1', 'Custom label 2'],
2044
- showSeriesNameInBar: true
2045
- });
2046
-
2047
- if (!report.valid) {
2048
- console.log('Errors:', report.errors);
2049
- console.log('Warnings:', report.warnings);
2050
- }
2051
- ```
2052
-
2053
- #### External Series Name Labels (`seriesNameLabels`)
2054
- You can position the series names outside the chart area as separate text boxes (`<p:sp>`) aligned with each corresponding bar or stack. These external labels automatically inherit the styling (font family, font size, bold, italic, color) defined in the template's series properties.
2055
-
2056
- Supported features:
2057
- * **Position**: Can be set to `'left'` or `'right'` to align text boxes to the left or right of the chart.
2058
- * **Auto-fit & Height Wrapping**: Automatically wraps text and calculates height if labels are longer than the available margin space.
2059
- * **Collision Detection**: Prevent overlapping with slide bounds by shrinking the chart, and resolve vertical overlaps of labels by shifting them apart.
2060
- * **Idempotency**: Safely clean up previous labels on multiple chart updates.
2061
-
2062
- Example usage:
2063
- ```javascript
2064
- ppt.useSlide(1).updateChart('RevenueChart', {
2065
- categories: ['Q1', 'Q2', 'Q3', 'Q4'],
2066
- series: [
2067
- { name: 'Product A', values: [100, 200, 300, 400] },
2068
- { name: 'Product B', values: [150, 250, 350, 450] }
2069
- ],
2070
- seriesNameLabels: {
2071
- enabled: true,
2072
- position: 'left', // 'left' or 'right'
2073
- autoFit: true // Automatically wrap and shrink layout if needed (default: true)
2074
- }
2075
- });
2076
- ```
2077
-
2078
- To validate your configuration and check for boundary or collision warning/errors:
2079
- ```javascript
2080
- const report = await ppt.useSlide(1).validateSeriesNameLabels('RevenueChart', {
2081
- enabled: true,
2082
- position: 'left',
2083
- autoFit: true
2084
- });
2085
-
2086
- if (!report.valid) {
2087
- console.error('Validation errors:', report.errors);
2088
- console.warn('Validation warnings:', report.warnings);
2089
- }
2090
- ```
2091
-
2092
- ---
2093
-
2094
- ## 📋 Native Lists (Bullet & Numbered Lists)
2095
-
2096
- PPTXForge supports native PowerPoint bullet lists and numbered lists across text placeholders, shapes, text boxes, table cells, and grouped shapes. When generating lists, the engine preserves run styles, custom bullet characters, indentation, and color overlays, generating valid OpenXML/DrawingML without repair alerts.
2097
-
2098
- ### 1. Basic Bullet List
2099
- Update a shape or text placeholder to be a bullet list:
2100
-
2101
- ```javascript
2102
- ppt.useSlide(1).updateText('Features', {
2103
- list: [
2104
- 'Fast PPTX generation',
2105
- 'OpenXML based',
2106
- 'Chart updates',
2107
- 'Table updates'
2108
- ]
2109
- });
2110
- ```
2111
-
2112
- ### 2. Numbered / Ordered List
2113
- Use the `ordered` flag to convert the list to a numbered format:
2114
-
2115
- ```javascript
2116
- ppt.useSlide(1).updateText('Steps', {
2117
- ordered: true,
2118
- list: [
2119
- 'Import template',
2120
- 'Update data',
2121
- 'Generate PPTX'
2122
- ]
2123
- });
2124
- ```
2125
- * Custom numbering systems can be specified with `style.numberType` (e.g., `arabicPeriod`, `alphaLcParen`, `romanUcPeriod`).
2126
-
2127
- ### 3. Nested / Multi-Level Lists
2128
- Construct hierarchy by passing objects containing a `text` string and a `children` array:
2129
-
2130
- ```javascript
2131
- ppt.useSlide(1).updateText('Requirements', {
2132
- list: [
2133
- 'Frontend',
2134
- {
2135
- text: 'Backend Development',
2136
- children: [
2137
- 'Node.js',
2138
- {
2139
- text: 'Databases',
2140
- children: ['MS SQL', 'PostgreSQL']
2141
- }
2142
- ]
2143
- }
2144
- ]
2145
- });
2146
- ```
2147
-
2148
- ### 4. Custom List Styling
2149
- Customize bullet characters, colors, sizes, and font properties:
2150
-
2151
- ```javascript
2152
- ppt.useSlide(1).updateText('KPIs', {
2153
- list: ['Revenue Up', 'Margins Normal'],
2154
- style: {
2155
- fontFamily: 'Arial',
2156
- fontSize: 18,
2157
- color: '#0055AA',
2158
- bulletColor: '#FF5500',
2159
- bulletChar: '✦',
2160
- bulletSize: 120 // Percentage relative to text (e.g. 120%)
2161
- }
2162
- });
2163
- ```
2164
-
2165
- ### 5. Table Cell Lists
2166
- You can also generate list hierarchies directly inside a cell of a DrawingML table:
2167
-
2168
- ```javascript
2169
- ppt.useSlide(3).updateTable('sales-table', [
2170
- ['Category', 'Performance details'],
2171
- ['North Region', '{{CellPlaceholder}}']
2172
- ]);
2173
-
2174
- ppt.updateText('CellPlaceholder', {
2175
- list: ['Table Bullet 1', 'Table Bullet 2']
2176
- });
2177
- ```
2178
-
2179
- ---
2180
-
2181
- ## 🔒 Advanced XML Security
2182
-
2183
- PPTXForge uses a secure XML parser that defends your application servers against common XML vulnerabilities.
2184
-
2185
- ### Built-in Protections
2186
- 1. **XML Bombs & Billion Laughs Mitigation**: Instantly rejects any XML payload containing `<!DOCTYPE>` or `<!ENTITY>` definitions, preventing parser lockups.
2187
- 2. **XXE Injection Defenses**: Completely blocks external entities referencing local files or external resources (e.g., `SYSTEM` or `PUBLIC`).
2188
- 3. **Decoupled Entity Expansion Limits**: Evaluates code points and standard characters (`&amp;`, `&lt;`, etc.) via a single-level parser, avoiding recursive parsing loops.
2189
-
2190
- ### Custom Security & Parsing API
2191
- Use the safe-parsing helpers to validate user-uploaded templates manually:
2192
- ```javascript
2193
- const { validateXml, safeParseXml } = require('node-pptx-templater');
2194
-
2195
- const schema = validateXml(userInputXml);
2196
- if (!schema.valid) {
2197
- console.error(`Invalid XML format: ${schema.error} on Line ${schema.line}`);
2198
- }
2199
- ```
2200
-
2201
- ---
2202
-
2203
- ## ⚡ Performance Benchmarks
2204
-
2205
- Below are benchmark results compiled on a standard Intel Core i7 system processing a 50-slide presentation template:
2206
-
2207
- | Operation | Average Duration |
2208
- | :--- | :--- |
2209
- | Load Template | ~110 ms |
2210
- | Scan & Replace 20 Text Tag Placeholders | ~2.5 ms |
2211
- | Validate XML Schemas & Relationship Integrity | ~14 ms |
2212
- | Table Row Cloning & Grid Merges (15 rows) | ~3 ms |
2213
- | Z-Order Re-indexing & Packaging Output | ~78 ms |
2214
-
2215
- ---
2216
-
2217
- ## ❓ FAQ & Developer Troubleshooting
2218
-
2219
- ### Q: PowerPoint displays a "Repair Presentation" alert when opening generated files.
2220
- * **Root Cause**: This is usually caused by:
2221
- 1. A missing relationship entry inside `.rels` maps (e.g., a slide refers to a chart file that isn't declared).
2222
- 2. Duplicate `<a16:rowId>` elements on a slide (caused by cloning rows raw without updating hashes).
2223
- * **Fix**: Ensure you always use the built-in `saveToFile()` or `toBuffer()` methods, which automatically execute validation checks, repair relationship indexes, and sanitize content structures.
2224
-
2225
- ### Q: A text placeholder is not replacing. How do I debug it?
2226
- * **Root Cause**: PowerPoint might have split your placeholder into multiple runs (e.g., `{{` and `placeholder}}`).
2227
- * **Fix**:
2228
- 1. Enable debug logging to locate the fragment: `PPTX_LOG_LEVEL=debug node app.js`.
2229
- 2. In PowerPoint, select the placeholder text box, cut it, and paste it back using the **"Keep Text Only"** option. This unifies the run.
2230
-
2231
- ---
2232
-
2233
- ## ⚡ Performance Optimization & Caching APIs
2234
-
2235
- The library provides first-class support for memory optimization, template caching, lazy loading, and streaming saves.
2236
-
2237
- ### 1. In-Memory Template Caching (IIS & Server Environments)
2238
- Instead of loading and parsing the PPTX ZIP structure from disk on every request, preload the template once. Subsequent templates can be instantiated from the cache in **0ms**:
2239
-
2240
- ```javascript
2241
- const { PPTXTemplater } = require('node-pptx-templater');
2242
-
2243
- // Preload templates into memory cache at server startup
2244
- await PPTXTemplater.preload('./templates/report.pptx');
2245
-
2246
- // Load from cache instantly inside request handlers
2247
- app.post('/generate-report', async (req, res) => {
2248
- const ppt = await PPTXTemplater.fromCache('./templates/report.pptx');
2249
-
2250
- ppt.useSlide(1).replaceText({ '{{title}}': req.body.title });
2251
-
2252
- const buffer = await ppt.toBuffer();
2253
- res.send(buffer);
2254
- });
2255
-
2256
- // Clear cache if templates change
2257
- PPTXTemplater.clearCache();
2258
- ```
2259
-
2260
- ### 2. Performance Profiling
2261
- Expose timing and memory metrics across the generation pipeline:
2262
-
2263
- ```javascript
2264
- const ppt = await PPTXTemplater.load('report.pptx');
2265
- ppt.enablePerformanceProfile();
2266
-
2267
- // Perform modifications...
2268
- ppt.useSlide(1).replaceText({ '{{title}}': 'Performance' });
2269
-
2270
- await ppt.toBuffer();
2271
-
2272
- // Retrieve timing statistics (in milliseconds)
2273
- const metrics = ppt.getPerformanceMetrics();
2274
- console.log(metrics);
2275
- /*
2276
- Output:
2277
- {
2278
- enabled: true,
2279
- templateLoadMs: 12.5,
2280
- parseMs: 45.2,
2281
- chartUpdateMs: 0,
2282
- imageUpdateMs: 0,
2283
- zipGenerationMs: 65.8,
2284
- totalMs: 125.4,
2285
- memoryUsedMB: 38.45
2286
- }
2287
- */
2288
- ```
2289
-
2290
- ### 3. Configurable ZIP Compression
2291
- Balance CPU execution time and file size when saving the presentation. Compression options support `'none' | 'fast' | 'balanced' | 'maximum'`:
2292
-
2293
- ```javascript
2294
- // balanced is the default (level 6 DEFLATE)
2295
- await ppt.save('output.pptx', { compression: 'balanced' });
2296
-
2297
- // maximum compression (level 9 DEFLATE) - best file size, slightly slower
2298
- await ppt.save('output.pptx', { compression: 'maximum' });
2299
-
2300
- // fast compression (level 1 DEFLATE) - fast packaging, good compression
2301
- await ppt.save('output.pptx', { compression: 'fast' });
2302
-
2303
- // none / store (0% compression) - extremely fast, skips compression entirely
2304
- const fastBuffer = await ppt.toBuffer({ compression: 'none' });
2305
- ```
2306
-
2307
- ### 4. Streaming Save & Streaming Image Input
2308
- Avoid buffering large output files in memory by saving directly to readable/writable streams. You can also pass Readable streams (like `fs.createReadStream`) directly to image APIs:
2309
-
2310
- ```javascript
2311
- const fs = require('fs');
2312
-
2313
- const ppt = await PPTXTemplater.load('report.pptx');
2314
-
2315
- // Stream image from file path without loading into memory buffer
2316
- const imageStream = fs.createReadStream('large-image.png');
2317
- await ppt.useSlide(1).replaceImage('placeholder-img', imageStream);
250
+ const result = await ppt.validatePresentation();
251
+ // → { valid: true, errors: [], warnings: [] }
2318
252
 
2319
- // Stream final PPTX directly to file disk or HTTP response
2320
- const writeStream = fs.createWriteStream('output.pptx');
2321
- await ppt.saveToStream(writeStream);
253
+ await ppt.repair(); // Auto-fix orphan relationships
254
+ await ppt.repairCharts(); // Fix broken chart workbook references
2322
255
  ```
2323
256
 
2324
257
  ---
2325
258
 
2326
- ## 🌐 IIS & Windows Server Deployment Guide
259
+ ## Migration from v1.0.x
2327
260
 
2328
- When deploying the library on **Windows Server** with **IIS** using `httpPlatformHandler` or `iisnode`, follow these production-ready recommendations:
261
+ No breaking changes. All existing APIs continue to work unchanged.
2329
262
 
2330
- 1. **Preload Large Templates**: Always call `await PPTXTemplater.preload(templatePath)` during application startup. This avoids high IIS request queue concurrency from competing for file handles or causing disk bottlenecks.
2331
- 2. **Use Streaming Saves**: For concurrent routes serving large PPTX outputs, use `saveToStream()` to stream data straight into the HTTP response stream rather than buffering the output as large Node buffers.
2332
- 3. **Optimize Compression**: If CPU cycles are a bottleneck on the IIS worker process, set `{ compression: 'fast' }` or `{ compression: 'none' }` on your save options.
2333
- 4. **Increase httpPlatformHandler Request Limits**: Ensure the `requestTimeout` and `maxConnections` settings in your IIS `web.config` are set appropriately to allow long-running file streaming tasks.
263
+ **New in v1.1.0:**
264
+ - `PPTXTemplater.load(path, { logLevel })` configure logging at load time
265
+ - `PPTXTemplater.setLogLevel(level)` global log level control
266
+ - `ppt.enableDebug()` instance debug shortcut
267
+ - `ppt.getTableRows(tableId, options)` — table data extraction
268
+ - `ppt.addTableRow(tableId, data, { mergeStrategy })` — nested row support
269
+ - `setGlobalLogLevel` / `resetLogLevel` now exported from public API
270
+ - 8 new example files
271
+ - `npm run docs:validate` — documentation validation
272
+ - `npm run docs:inventory` — feature inventory generation
2334
273
 
2335
274
  ---
2336
275
 
2337
- ## 🤝 Contributing
276
+ ## Contributing
2338
277
 
2339
- We welcome contributions from the community. Please read our [CONTRIBUTING.md](./CONTRIBUTING.md) to set up the development environment, format code, and submit Pull Requests.
278
+ Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) and open a pull request.
2340
279
 
2341
280
  ```bash
2342
281
  git clone https://github.com/jsuyog2/node-pptx-templater.git
@@ -2347,6 +286,6 @@ npm test
2347
286
 
2348
287
  ---
2349
288
 
2350
- ## 📄 License
289
+ ## License
2351
290
 
2352
- Licensed under the MIT License. © node-pptx-templater contributors.
291
+ [MIT](./LICENSE) © node-pptx-templater contributors