node-pptx-templater
A low-level, high-performance PowerPoint template engine built for Node.js. Populate slides dynamically using visually designed PowerPoint files, bypassing PowerPoint corruption warnings with unique OpenXML integrity features.
No Office Dependencies
Pure JavaScript execution. Runs flawlessly on AWS Lambda, Vercel Edge, or Google Cloud serverless platforms.
Fragment Resolution
PowerPoint editor splits tags (e.g. {{c, ompany}}). The engine merges them back automatically for flawless replacements.
Excel Sync Caching
Synchronizes slide chart coordinates and visual datasets inside the underlying Excel sheet, avoiding PowerPoint refresh alerts.
Visual Design vs Code Automation
Stop compiling slide elements inside complex code blocks. Design slide decks visually in PowerPoint, Keynote, or Google Slides, set formats and alignments, insert placeholders like {{name}}, and let node-pptx-templater populate them dynamically.
Installation & Onboarding
Set up the library in less than 30 seconds using npm or yarn. Zero local configurations required.
NPM Install
npm install node-pptx-templater
Prerequisites
- Node.js Engine: Version
>= 18.0.0(fully supports CommonJS standard require). - Package Platforms: Compiles natively on Windows, macOS, Linux, and Edge runtimes.
Quick Start Guide
Use this template rendering code snippet to load, populate, and export your first slide presentation.
const { PPTXTemplater } = require('node-pptx-templater');
async function main() {
// 1. Load the presentation template
const ppt = await PPTXTemplater.load('monthly_report_template.pptx');
// 2. Select slide 1 and execute text replacement
ppt.useSlide(1)
.replaceTextByTag('title', 'Quarterly Earnings Report')
.replaceMultiple({
company: 'Acme Corporation',
year: '2026'
});
// 3. Save the presentation to disk
await ppt.saveToFile('./output/annual_earnings.pptx');
console.log('Presentation generated successfully!');
}
main().catch(err => console.error(err));
Learning Paths
Select a path tailored to your architectural expertise and PPTX templating requirements.
Path 1: Standard Replacements & Text Merges
Ideal for replacing simple placeholder strings and inserting logos or target photos. Learn how placeholders look, how to format text inside PowerPoint, and execute basic save actions.
- Designing simple
{{tag}}placeholders in your editor. - Replacing single tags and mapping values objects.
- Substituting template images while keeping shapes coordinates.
Path 2: Presentation Duplication & Element Collections
For developers building reports containing multiple tables, maps, series charts, and cloned shapes. Learn how to duplicate slides and manage relationships safely.
- Cloning, deleting, and reordering slides dynamically.
- Updating chart databases categories and series points.
- Cloning slide table rows with unique rowId metadata.
Path 3: Stacking Layer Z-Order & Custom Slide Imports
Optimize execution speeds, implement complex layer stack sorting, import slides from distinct templates, and audit content overrides package integrity.
- Stacking shapes layers using
bringForwardandsendToBack. - Importing slides from distinct presentations with asset deduplication.
- Checking relationship lists with structural validation tools.
Interactive Showcase Sandbox
Click a feature tab on the left to see the code snippet and a visual representation of how PowerPoint is modified in real-time.
ppt.useSlide(1)
.replaceTextByTag('title', 'Q2 Report')
.replaceMultiple({
user: 'Acme Corp',
date: 'June 2026'
});
Table Cell Merging
OpenXML PowerPoint tables require precise cell spans coordinate structures. The top-left cell acts as the **origin**, declaring `gridSpan` and `rowSpan`. The remaining shadowed cells must flag `hMerge` and `vMerge` to avoid breaking PowerPoint table layout models.
API-based merging
Call mergeCells() directly by supplying coordinates:
ppt.mergeCells({
tableId: 'sales-table',
startRow: 1,
startCol: 1,
endRow: 2,
endCol: 2
});
Template-driven cell formatting
Update table values and declare spans inline within cell data:
ppt.updateTable('sales-table', [
['Header', 'Header', 'Header'],
['Data', { value: 'Span 2 Cols', colSpan: 2 }],
['Data', 'Data', { value: 'Span 2 Rows', rowSpan: 2 }]
]);
Table Cell Shapes
The cell shape engine dynamically creates and positions shapes (like indicators, progress bars, badges, and icons) inside table cells. It simulates text wrapping and paragraph layout to calculate row expansion, anchoring shapes relative to the actual cell boundaries.
Cell Relative Positioning
Coordinates are relative to the cell's top-left corner in pixels rather than slide coordinates. Offsets are automatically constrained within cell boundaries to prevent escaping.
await ppt.addCellShape('Table', 1, 2, {
type: 'circle',
x: 10,
y: 10,
width: 15,
height: 15,
anchor: 'cell' // Default
});
Dynamic Row Height & Wrapped Text Support
Automatically recalculates cell dimensions when long paragraphs or wrapped texts expand row heights, keeping shapes aligned with cell flow.
ppt.updateTable('Table', {
rows: [
{ A: 'Very long wrapped text...', V: 'Active' }
],
cellShapes: {
V: () => ({
type: 'progressBar',
value: 75,
position: 'middle-right'
})
}
});
Cell Alignment Modes & Presets
Position shapes automatically using 9 standard presets or explicit alignX / alignY alignment anchors:
await ppt.addCellShape('Table', 1, 1, {
type: 'badge',
text: 'NEW',
position: 'bottom-center' // 9 alignment options
});
Merged Cell Support & Helpers
Correctly maps cell boundaries for cells spanned with rowSpan and colSpan. Retrieve final coordinates via helpers:
// Get final cell bounds and position in pixels
const bounds = ppt.getCellBounds('Table', 1, 1);
const pos = ppt.getCellPosition('Table', 1, 1);
Excel Chart Update
PowerPoint embeds an Excel worksheet (`ppt/embeddings/`) that controls chart datasets. Standard scripts only edit visual chart coordinates, corrupting calculations. node-pptx-templater compiles updates for both XML caches and spreadsheet rows.
ppt.updateChartData('sales-chart', {
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
series: [
{ name: 'Target', values: [100, 120, 140, 160] },
{ name: 'Revenue', values: [105, 118, 145, 172] }
]
});
Z-Order & Stacking Layers
Programmatically stack shapes, images, charts, and tables using layer indices. The engine translates commands (Bring Forward, Send to Back) directly into OpenXML element orders within slide `<p:spTree>` blocks.
// See all slide elements layers in stacking order (bottom to top)
const elements = ppt.getObjectOrder(1);
console.log(elements);
// Bring the overlay logo shape to the front
ppt.bringToFront({ slide: 1, objectId: 'Logo' });
// Send the background template banner shape to the bottom
ppt.sendToBack({ slide: 1, objectId: 'Background' });
Chart Data Labels
Custom chart annotations help emphasize critical data points. The engine integrates custom values, cell range bindings, maps, and layouts seamlessly into the OpenXML slide cache and the backing Excel spreadsheet.
Value From Cells
Pull labels directly from worksheet range cells:
ppt.useSlide(1).updateDataLabels('SalesChart', {
series: 0,
labelsFromCells: 'Sheet1!D2:D10'
});
Custom Label Arrays
Define manual string labels for each data point:
ppt.useSlide(1).updateDataLabels('KPIChart', {
series: 0,
labels: ['Excellent', 'Average', 'Poor']
});
Label Templates
Build dynamic annotations by combining values, percentage metrics, series names, and categories inside text run templates.
ppt.useSlide(1).updateDataLabels('RevenueChart', {
series: 0,
template: '{category} performance: {value} ({percentage}%)'
});
Label Styling
Configure typography, sizes, weights, and colors. The engine generates standard DrawingML definitions (<c:txPr>) to preserve visual rendering quality.
ppt.useSlide(1).updateDataLabels('KPIChart', {
series: 0,
labels: ['High', 'Medium', 'Low'],
labelStyle: {
fontFamily: 'Trebuchet MS',
fontSize: 14,
color: '#00AAFF',
bold: true,
italic: true,
underline: true
}
});
Label Positions
Position custom annotations relative to data points. The engine maps alignment strings to valid OpenXML schema tags.
ppt.useSlide(1).updateDataLabels('MarketSharePie', {
series: 0,
position: 'bestFit', // 'center', 'insideEnd', 'insideBase', 'outsideEnd', etc.
showPercent: true
});
Label Formatting
Custom inline label formatting within updateChart() series values allows defining custom labels without separate function calls.
ppt.useSlide(1).updateChart('RevenueChart', {
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
series: [{
name: 'Product A',
values: [
{ data: 145, label: 'Q1: 145 (Low)' },
{ data: 210, label: 'Q2: 210 (Med)' },
{ data: 190, label: 'Q3: 190 (Med)' },
{ data: 250, label: 'Q4: 250 (High)' }
]
}]
});
Tables API
Manipulate DrawingML tables, rows, cells, auto-fitting, resizing, and cell merging.
updateTable
Replaces table rows with new data in the selected slide(s). Preserves borders, merged cells, fonts, colors, and alignment from the template.
If tableId is not found, throws TableNotFoundError. Coordinates outside structural table dimensions fail silently or align incorrectly depending on row dimensions.
Updates `<a:t>` element text inside individual table cells under `<a:tc>`, adjusting `<a:tcPr>` border styles and alignment rules.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rows | string[][] | 2D array of cell values (row × col). |
ppt.useSlide(1).updateTable('summary-table', [
['Item', 'Value'],
['Widgets', '1,200'],
['Gadgets', '850']
]);
ppt.useSlide(2).updateTable('details-table', [
['Product', 'Revenue', { value: 'Growth', align: 'ctr', fill: '22c55e', bold: true }],
['SaaS', '$45,000', '15.4%'],
['Licensing', '$12,000', '-2.1%']
]);
const reportData = await fetchReportMetrics();
ppt.useSlide(3)
.updateTable('sales-table', [
['Q1 Metric', 'Performance', 'Target Margin'],
...reportData.map(r => [
r.metric,
{ value: r.perf, fill: r.perf >= r.target ? '10b981' : 'ef4444' },
r.target
])
]);
getTableRows
Extracts table data from the active slide as structured JSON. The first row of the table is treated as the header row.
If tableId is not found, throws TableNotFoundError. Merged cells automatically resolve to their parent cell value.
Reads XML table data structure. No write impact on slide XML.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| [options] | Object | Extraction options. |
| [options.raw=false] | boolean | Return `string[][]` instead of object array. |
| [options.includeMetadata=false] | boolean | Return `{rows, rowCount, columnCount, mergedCells}`. |
const rows = await ppt.getTableRows('SalesTable');
const rows = await ppt.getTableRows('SalesTable', { raw: true });
const data = await ppt.getTableRows('SalesTable', { includeMetadata: true });
console.log(`RowCount: ${data.rowCount}, ColCount: ${data.columnCount}`);
addTableRow
Appends one or more rows to a table. Supports flat arrays and nested arrays for rowspan-merged cells. `'rowspan'` creates OpenXML vertical spans, `'auto'` merges identical adjacent values, `'none'` expands nested arrays into multiple flat rows.
Target table must exist. Row array must match table column count, otherwise cells are padded or truncated.
Appends a `<a:tr>` child block to the table, and assigns a unique collaborative ID `<a16:rowId>` to prevent file corruption.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowData | Array<string|Array<string>> | Row data. Nested arrays create rowspan cells. |
| [options] | Object | Row insertion options. |
| [options.mergeStrategy='rowspan'] | 'rowspan'|'auto'|'none' | How to handle nested arrays. |
ppt.useSlide(1).addTableRow('data-table', ['John Doe', 'Sales Manager', '$120k']);
// Add a styled row
ppt.useSlide(1).addTableRow('data-table', [
'Jane Smith',
{ value: 'Director', bold: true, align: 'ctr' },
{ value: '$180k', fill: '10b981' }
]);
users.forEach(u => {
ppt.addTableRow('user-list-table', [u.name, u.role, u.salary]);
});
removeTableRow
Removes a row from a table by its 0-based row index.
Index must fall within table bounds (0 to rows.length - 1). Deleting the last row of a table leaves it structurally empty, which might alert alerts in PowerPoint.
Removes the target `<a:tr>` node entirely from the slide table XML.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index to remove. |
ppt.useSlide(1).removeTableRow('data-table', 2);
// Delete the second row (index 1)
ppt.useSlide(1).removeTableRow('data-table', 1);
const tables = ppt.getTables();
const targetTable = tables.find(t => t.id === 'user-table');
if (targetTable && targetTable.rows > 5) {
ppt.removeTableRow('user-table', targetTable.rows - 1);
}
insertTableRow
Inserts a new row at the specified 0-based index, shifting existing rows down.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based index at which to insert the new row. |
| rowData | Array<string> | Cell values for the new row. |
ppt.useSlide(1).insertTableRow(tableId, rowIndex, rowData);
ppt.useSlide(1).insertTableRow(tableId, rowIndex, rowData); // Fluent wrapper implementation
try {
ppt.useSlide(1).insertTableRow(tableId, rowIndex, rowData);
} catch (err) {
console.error('API Error: ', err);
}
cloneTableRow
Clones a row and inserts the copy at a target position.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| sourceRowIndex | number | 0-based index of the row to clone. |
| targetRowIndex | number | 0-based index where the clone is inserted. |
ppt.useSlide(1).cloneTableRow(tableId, sourceRowIndex, targetRowIndex);
ppt.useSlide(1).cloneTableRow(tableId, sourceRowIndex, targetRowIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).cloneTableRow(tableId, sourceRowIndex, targetRowIndex);
} catch (err) {
console.error('API Error: ', err);
}
updateCell
Updates the text and optional formatting of a single table cell.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| value | string | New cell text content. |
| [options] | Object | Cell formatting options. |
| [options.bold] | boolean | Bold text. |
| [options.italic] | boolean | Italic text. |
| [options.fontSize] | number | Font size in points. |
| [options.align] | 'left'|'center'|'right' | Text alignment. |
| [options.fill] | string | Cell background color (hex, e.g. '#FF0000'). |
| [options.color] | string | Text color (hex). |
ppt.useSlide(1).updateCell(tableId, rowIndex, colIndex, value, options = {});
ppt.useSlide(1).updateCell(tableId, rowIndex, colIndex, value, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).updateCell(tableId, rowIndex, colIndex, value, options = {});
} catch (err) {
console.error('API Error: ', err);
}
mergeCells
Merges a rectangular region of table cells into a single merged cell. Supports both positional arguments and an options object.
Start Row/Col must be less than or equal to End Row/Col. Cells outside the grid boundaries throw RangeError.
Declares `gridSpan` and `rowSpan` in the top-left origin `<a:tc>`, and applies `hMerge="1"` or `vMerge="1"` properties to all shadowed cells inside the merged region block.
| Parameter | Type | Description |
|---|---|---|
| tableIdOrOptions | string|Object | Table ID string, or options object with all fields. |
| [startRow] | number | 0-based start row. |
| [startCol] | number | 0-based start column. |
| [endRow] | number | 0-based end row (inclusive). |
| [endCol] | number | 0-based end column (inclusive). |
ppt.useSlide(1).mergeCells('metrics-table', 1, 1, 2, 2);
// Pass coordinates config directly as an object
ppt.mergeCells({
tableId: 'metrics-table',
slide: 1,
startRow: 0,
startCol: 0,
endRow: 1,
endCol: 2
});
if (ppt.validateMergeRegion('stats-table', 1, 1, 3, 2).valid) {
ppt.mergeCells('stats-table', 1, 1, 3, 2);
} else {
console.warn('Cannot merge cells: overlapping region');
}
unmergeCells
Unmerges (splits) a previously merged cell region. Supports both positional arguments and an options object.
Target must overlap an active merge region origin. Calling on an unmerged region acts as a no-op.
Removes `gridSpan`, `rowSpan`, `hMerge`, and `vMerge` attributes from all target cells in the region.
| Parameter | Type | Description |
|---|---|---|
| tableIdOrOptions | string|Object | Table ID string, or options object. |
| [startRow] | number | 0-based start row of the merged region. |
| [startCol] | number | 0-based start column. |
| [endRow] | number | 0-based end row. |
| [endCol] | number | 0-based end column. |
ppt.useSlide(1).unmergeCells('metrics-table', 1, 1, 2, 2);
// Target a specific cell inside the merge to split it
ppt.unmergeCells({
tableId: 'metrics-table',
slide: 1,
row: 1,
col: 1
});
const regions = ppt.getMergedCells('data-table');
regions.forEach(reg => {
if (reg.startRow === 0) {
ppt.unmergeCells('data-table', reg.startRow, reg.startCol, reg.endRow, reg.endCol);
}
});
getMergedCells
Returns an array of all merged cell regions in a table.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [tableId] | string | Table name or shape ID. Defaults to the first table found. |
ppt.useSlide(1).getMergedCells(tableId);
ppt.useSlide(1).getMergedCells(tableId); // Fluent wrapper implementation
try {
ppt.useSlide(1).getMergedCells(tableId);
} catch (err) {
console.error('API Error: ', err);
}
validateMergeRegion
Validates whether a merge region is valid for the given table dimensions. Checks for overlapping merges, out-of-bounds coordinates, etc.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| startRow | number | 0-based start row. |
| startCol | number | 0-based start column. |
| endRow | number | 0-based end row. |
| endCol | number | 0-based end column. |
ppt.useSlide(1).validateMergeRegion(tableId, startRow, startCol, endRow, endCol);
ppt.useSlide(1).validateMergeRegion(tableId, startRow, startCol, endRow, endCol); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateMergeRegion(tableId, startRow, startCol, endRow, endCol);
} catch (err) {
console.error('API Error: ', err);
}
isMergedCell
Checks whether a specific table cell is part of a merged region.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| row | number | 0-based row index. |
| col | number | 0-based column index. |
ppt.useSlide(1).isMergedCell(tableId, row, col);
ppt.useSlide(1).isMergedCell(tableId, row, col); // Fluent wrapper implementation
try {
ppt.useSlide(1).isMergedCell(tableId, row, col);
} catch (err) {
console.error('API Error: ', err);
}
getMergeParent
Returns the anchor (parent) cell coordinates of a merged region that contains the given cell.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| row | number | 0-based row index of any cell in the merged region. |
| col | number | 0-based column index. |
ppt.useSlide(1).getMergeParent(tableId, row, col);
ppt.useSlide(1).getMergeParent(tableId, row, col); // Fluent wrapper implementation
try {
ppt.useSlide(1).getMergeParent(tableId, row, col);
} catch (err) {
console.error('API Error: ', err);
}
getMergeRegion
Returns the full extent of the merged region containing a given cell.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| row | number | 0-based row index of any cell in the merged region. |
| col | number | 0-based column index. |
ppt.useSlide(1).getMergeRegion(tableId, row, col);
ppt.useSlide(1).getMergeRegion(tableId, row, col); // Fluent wrapper implementation
try {
ppt.useSlide(1).getMergeRegion(tableId, row, col);
} catch (err) {
console.error('API Error: ', err);
}
splitMergedRegion
Splits a previously merged cell region back into individual cells.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| row | number | 0-based row of the merged region anchor. |
| col | number | 0-based column of the merged region anchor. |
ppt.useSlide(1).splitMergedRegion(tableId, row, col);
ppt.useSlide(1).splitMergedRegion(tableId, row, col); // Fluent wrapper implementation
try {
ppt.useSlide(1).splitMergedRegion(tableId, row, col);
} catch (err) {
console.error('API Error: ', err);
}
cloneMergedRegion
Clones an existing merged region to a new anchor position in the table.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| row | number | 0-based row of the source merged region. |
| col | number | 0-based column of the source merged region. |
| targetRow | number | 0-based target row. |
| targetCol | number | 0-based target column. |
ppt.useSlide(1).cloneMergedRegion(tableId, row, col, targetRow, targetCol);
ppt.useSlide(1).cloneMergedRegion(tableId, row, col, targetRow, targetCol); // Fluent wrapper implementation
try {
ppt.useSlide(1).cloneMergedRegion(tableId, row, col, targetRow, targetCol);
} catch (err) {
console.error('API Error: ', err);
}
autoFitTable
Automatically adjusts column widths to fit the content of each cell.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
ppt.useSlide(1).autoFitTable(tableId);
ppt.useSlide(1).autoFitTable(tableId); // Fluent wrapper implementation
try {
ppt.useSlide(1).autoFitTable(tableId);
} catch (err) {
console.error('API Error: ', err);
}
resizeTable
Resizes a table to the specified width and height in EMUs. 1 inch = 914,400 EMUs.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| width | number | New width in EMUs. |
| height | number | New height in EMUs. |
ppt.useSlide(1).resizeTable(tableId, width, height);
ppt.useSlide(1).resizeTable(tableId, width, height); // Fluent wrapper implementation
try {
ppt.useSlide(1).resizeTable(tableId, width, height);
} catch (err) {
console.error('API Error: ', err);
}
getTables
Returns metadata for all tables on the targeted slide(s).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getTables();
ppt.useSlide(1).getTables(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getTables();
} catch (err) {
console.error('API Error: ', err);
}
addCellShape
Dynamically adds a shape inside a table cell based on cell coordinates. Cell shapes are overlay graphics anchored independently of the table layout, and adding a cell shape never modifies row heights, column widths, or table dimensions.
Index must fall within table bounds. Coordinates outside structural table dimensions align relative to cell borders.
Appends a `<p:sp>` shape node aligned to cell EMUs.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| options | Object | Shape configuration options. |
await ppt.addCellShape('Table', 1, 2, { type: 'circle', fill: '#10B981' });
updateCellShape
Updates an existing shape inside a table cell.
Target shape index must exist in cell.
Updates target `<p:sp>` attributes inside the slide XML.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| shapeIndex | number | 0-based shape index in the cell. |
| options | Object | Shape configuration properties to update. |
await ppt.updateCellShape('Table', 1, 2, 0, { fill: '#EF4444' });
removeCellShape
Removes a shape from a table cell.
Shape must exist in cell.
Deletes `<p:sp>` shape node from the slide XML.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| shapeIndex | number | 0-based shape index in the cell. |
await ppt.removeCellShape('Table', 1, 2, 0);
getCellShape
Discovers and retrieves details of an existing cell shape on the targeted slide.
Retrieves details of shape in table cell.
None (read-only query).
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| shapeIndex | number | 0-based shape index in the cell. |
const shape = ppt.getCellShape('Table', 1, 2, 0);
getCellBounds
Retrieves final rendered bounds of a table cell in pixels.
Returns null if the slide table cannot be resolved or slide selection is empty.
Reads table coordinates and layout properties. No write impact on slide XML.
| Parameter | Type | Description |
|---|---|---|
| tableIdOrObj | string|Object | Table name, shape ID, or table object. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
const bounds = ppt.getCellBounds('summary-table', 1, 1);
const { x, y, width, height } = ppt.getCellBounds('summary-table', 1, 1);
getCellPosition
Retrieves final rendered position of a table cell in pixels. Optionally calculates centered top-left coordinates for a shape of given dimensions.
Returns null if the slide table cannot be resolved.
Reads cell positioning data in pixels. No write impact on slide XML.
| Parameter | Type | Description |
|---|---|---|
| tableIdOrObj | string|Object | Table name, shape ID, or table object. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| [shapeWidthOrOptions] | number|Object | Width of the shape in pixels, or options object. |
| [shapeHeight] | number | Height of the shape in pixels. |
const pos = ppt.getCellPosition('summary-table', 1, 1);
const { row, column, x, y } = ppt.getCellPosition('summary-table', 1, 1);
Charts API
Sync category series, update Excel spreadsheets data caches, change titles, and manage charts.
updateChart
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.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or relationship ID. |
| data | ChartData | New chart data. |
| data.categories | string[] | Category labels (X-axis). |
| data.series | SeriesData[] | Data series array. |
| data.series[].name | string | Series name. |
| data.series[].values | number[]|object[] | Data values (numbers or label objects). |
ppt.useSlide(1).updateChart(chartId, data);
ppt.useSlide(1).updateChart(chartId, data); // Fluent wrapper implementation
try {
ppt.useSlide(1).updateChart(chartId, data);
} catch (err) {
console.error('API Error: ', err);
}
validateCharts
Validates all charts in the presentation to ensure they are not corrupted. Checks XML, caches, and embedded workbook references.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).validateCharts();
ppt.useSlide(1).validateCharts(); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateCharts();
} catch (err) {
console.error('API Error: ', err);
}
repairCharts
Repairs common chart corruption issues such as broken caches, missing embedded workbooks, or orphan nodes.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).repairCharts();
ppt.useSlide(1).repairCharts(); // Fluent wrapper implementation
try {
ppt.useSlide(1).repairCharts();
} catch (err) {
console.error('API Error: ', err);
}
updateChartData
Alias for `updateChart()`. Updates chart data for a named chart.
Dataset categories and series coordinates must match initial chart mappings structure to avoid Excel workbook cell mismatches.
Rewrites numerical categories and series data caches in chart XML, and updates cell values in the backing `ppt/embeddings/*.xlsx` workbook in the ZIP archive.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| data | Object | Chart data object with `categories` and `series`. |
ppt.useSlide(1).updateChartData('sales-chart', {
categories: ['Q1', 'Q2'],
series: [{ name: 'Actual', values: [100, 150] }]
});
ppt.useSlide(2).updateChartData('sales-chart', {
categories: ['Jan', 'Feb', 'Mar'],
series: [
{ name: 'Target', values: [100, 120, 140] },
{ name: 'Actual', values: [105, 118, 145] }
]
});
const salesData = await fetchSalesData();
ppt.useSlide(1).updateChartData('revenue-gauge', {
categories: salesData.months,
series: [
{ name: 'Direct Sales', values: salesData.direct },
{ name: 'Channel Sales', values: salesData.channel }
]
});
replaceChartSeries
Replaces a specific data series in a chart.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| seriesIndex | number | 0-based index of the series to replace. |
| newSeriesData | Object | New series data `{ name, values }`. |
ppt.useSlide(1).replaceChartSeries(chartId, seriesIndex, newSeriesData);
ppt.useSlide(1).replaceChartSeries(chartId, seriesIndex, newSeriesData); // Fluent wrapper implementation
try {
ppt.useSlide(1).replaceChartSeries(chartId, seriesIndex, newSeriesData);
} catch (err) {
console.error('API Error: ', err);
}
updateChartTitle
Updates only the title text of a chart.
If the template chart has no initial title layout block, adding a title might require injecting new XML blocks.
Finds and replaces text run values inside `<c:title>` and child `<a:t>` nodes under chart structure.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| title | string | New chart title. |
ppt.useSlide(1).updateChartTitle('sales-chart', 'Quarterly Metrics Overview');
ppt.useSlide(2).updateChartTitle('revenue-chart', 'Global SaaS Revenue (2026)');
const q = getActiveQuarter();
ppt.useSlide(1).updateChartTitle('kpi-chart', `Quarter ${q} Performance Summary`);
updateChartCategories
Updates only the category labels (X-axis) of a chart, keeping values unchanged.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| categories | string[] | Array of category label strings. |
ppt.useSlide(1).updateChartCategories(chartId, categories);
ppt.useSlide(1).updateChartCategories(chartId, categories); // Fluent wrapper implementation
try {
ppt.useSlide(1).updateChartCategories(chartId, categories);
} catch (err) {
console.error('API Error: ', err);
}
updateDataLabels
Updates data labels for a specific chart series. Supports custom arrays, label maps, template strings, and cell references.
If options.series exceeds available series in the chart, an out of bounds error is thrown. Cell range formats in labelsFromCells must match valid worksheet notation.
Generates and appends a `<c:dLbls>` block inside the targeted series `<c:ser>` node in the chart XML, setting flags and custom values, and synchronizes the backing workbook.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| options | Object | Data label options. |
| [options.series=0] | number | 0-based series index. |
| [options.labels] | string[] | Array of custom label strings. |
| [options.labelMap] | Object | Map of `{ categoryValue: label }`. |
| [options.template] | string | Template string with `{value}`, `{category}`, `{percentage}` tokens. |
| [options.labelsFromCells] | string | Excel cell range (e.g. `'Sheet1!$C$2:$C$6'`). |
| [options.showSeriesNameInBar] | boolean | Prepend series name to bar chart labels. |
ppt.useSlide(1).updateDataLabels('SalesChart', {
series: 0,
labels: ['Excellent', 'Good', 'Poor']
});
// Use cell range from embedded worksheet for custom labels
ppt.useSlide(1).updateDataLabels('SalesChart', {
series: 0,
labelsFromCells: 'Sheet1!D2:D4'
});
// Apply templates, custom positions, and fonts to data labels
ppt.useSlide(1).updateDataLabels('SalesChart', {
series: 0,
template: '{category}: {value}',
position: 'insideEnd',
labelStyle: {
fontFamily: 'Arial',
fontSize: 12,
bold: true,
color: '#FF0000'
}
});
getDataLabels
Retrieves the current data labels configuration for a specific chart series.
Returns an empty array if the targeted series index has no custom data label overrides or does not exist.
Reads individual `<c:dLbl>` values and structures from `<c:dLbls>` inside slide chart XML caches.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| [options] | Object | Options. |
| [options.series=0] | number | 0-based series index. |
const labels = await ppt.useSlide(1).getDataLabels('SalesChart', { series: 0 });
console.log(labels); // [{ point: 0, value: 'Excellent' }, ...]
const labels = await ppt.getDataLabels('SalesChart', { series: 1 });
// Extract and log all custom data labels for a chart
try {
const labels = await ppt.useSlide(1).getDataLabels('KPIChart', { series: 0 });
labels.forEach(lbl => {
console.log(`Data Point ${lbl.point} Override: ${lbl.value}`);
});
} catch (err) {
console.error('Failed to read data labels:', err);
}
validateDataLabels
Validates the data labels configuration for a chart series against the chart XML.
Ensures the series count matches bounds and cell formats conform to correct patterns (e.g. Sheet1!A1:B2).
Dry-runs verification of dimensions, structures, and references without writing updates to the ZIP archive.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| [options] | Object | Options (same as `updateDataLabels`). |
const result = await ppt.useSlide(1).validateDataLabels('SalesChart', {
labels: ['High', 'Low']
});
console.log(result.valid);
const result = await ppt.validateDataLabels('SalesChart', {
labelsFromCells: 'Sheet1!D2:D10'
});
const check = await ppt.useSlide(1).validateDataLabels('SalesChart', {
labels: ['High', 'Medium', 'Low'],
position: 'invalidPosition'
});
if (!check.valid) {
console.warn('Configuration errors detected:', check.errors.join('\n'));
}
validateChartLabels
Validates chart data labels across all series, including cell reference checks.
Ensures the targeted chart is stacked and the series details/style properties are present in the template.
Reads template dLbls properties and layout data structure to identify potential visual alignment and rendering issues.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| [options] | Object | Options. |
const result = await ppt.useSlide(1).validateChartLabels('SalesChart', {
labels: ['High', 'Low']
});
console.log(result.valid);
const result = await ppt.validateChartLabels('SalesChart', {
showSeriesNameInBar: true
});
const check = await ppt.useSlide(1).validateChartLabels('SalesChart', {
labels: ['A', 'B', 'C', 'D'],
showSeriesNameInBar: true
});
if (!check.valid) {
console.warn('Chart label warnings/errors:', check.warnings, check.errors);
}
validateSeriesNameLabels
Validates series name labels (the labels showing series names inside bar chart bars).
Checks slide boundaries collision and ensures options.position is either "left" or "right".
Dry-runs verification of options structure, slide limits, and chart area coordinate references.
| Parameter | Type | Description |
|---|---|---|
| chartId | string | Chart name or shape ID. |
| [options] | Object | Options. |
const result = await ppt.useSlide(1).validateSeriesNameLabels('SalesChart', {
enabled: true,
position: 'left'
});
console.log(result.valid);
const result = await ppt.validateSeriesNameLabels('SalesChart', {
enabled: true,
position: 'right',
autoFit: true
});
const check = await ppt.useSlide(1).validateSeriesNameLabels('SalesChart', {
enabled: true,
position: 'left',
autoFit: true
});
if (!check.valid) {
console.error('Validation errors:', check.errors);
}
getCharts
Returns an array of all charts found on the targeted slide(s).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getCharts();
ppt.useSlide(1).getCharts(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getCharts();
} catch (err) {
console.error('API Error: ', err);
}
getChartLabelPositions
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).
Returns exact coordinate positions of data labels on the slide. Chart must be present and updated.
Reads template geometry layouts and maps plotArea bounds to slide coordinates.
| Parameter | Type | Description |
|---|---|---|
| chartId | string |
const positions = await ppt.useSlide(1).getChartLabelPositions('SalesChart');
const positions = await ppt.getChartLabelPositions('SalesChart');
console.log(positions[0]); // { series: 'A', category: 'Q1', x: 1200000, y: 1500000, ... }
const positions = await ppt.useSlide(1).getChartLabelPositions('ChartId');
positions.forEach(pos => {
console.log(`Label at X:${pos.x}, Y:${pos.y}`);
});
getChartBarPositions
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).
Returns exact coordinates of bars/columns. Bounding box coordinates represent absolute slide positions.
Reads template chart series layout data and calculates exact bar locations.
| Parameter | Type | Description |
|---|---|---|
| chartId | string |
const bars = await ppt.useSlide(1).getChartBarPositions('SalesChart');
const bars = await ppt.getChartBarPositions('SalesChart');
console.log(bars[0]); // { series: 'A', category: 'Q1', x: 1000000, y: 1400000, ... }
const bars = await ppt.useSlide(1).getChartBarPositions('ChartId');
bars.forEach(b => {
console.log(`Bar at X:${b.x}, Y:${b.y}, Width:${b.width}, Height:${b.height}`);
});
addTextAtPosition
Adds a textbox shape at a specific EMU coordinate position on targeted slides. Supports custom font styling and alignment configuration.
Adds a textbox shape directly to the slide at the specified coordinate layout position.
Creates and inserts a new `<p:sp>` shape component node at the end of the slide `<p:spTree>` list.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.text | string | |
| options.x | number | |
| options.y | number | |
| [options.width=1200000] | number | |
| [options.height=300000] | number | |
| [options.style] | Object |
ppt.useSlide(1).addTextAtPosition({
text: 'Label',
x: 1000000,
y: 1000000
});
ppt.addTextAtPosition({
text: 'Header',
x: 500000,
y: 500000,
width: 2000000,
height: 500000,
style: { fontSize: 12, bold: true, color: '#FF0000' }
});
ppt.useSlide(1).addTextAtPosition({
text: 'Confidential',
x: 8000000,
y: 100000,
style: { fontSize: 10, italic: true, color: '#777777' }
});
addTextNearChartLabel
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.
Detects collision and places textboxes nicely next to chart data labels. Position must be left or right.
Determines target label coordinates and appends aligned text shape `<p:sp>` elements.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.chart | string | |
| options.text | string|Function | |
| [options.position='left'] | 'left'|'right' | |
| [options.style] | Object |
ppt.addTextNearChartLabel({
chart: 'SalesChart',
text: 'Series',
position: 'left'
});
ppt.useSlide(1).addTextNearChartLabel({
chart: 'Chart',
text: ({ series }) => `Near ${series}`,
position: 'right',
style: { fontSize: 11, italic: true, color: '#333333' }
});
ppt.useSlide(1).addTextNearChartLabel({
chart: 'RevenueChart',
text: ({ category, value }) => `${category}: ${value}`,
position: 'left',
style: { fontSize: 10, fontFamily: 'Arial' }
});
Slides API
Duplicate, move, import, delete, and structure layout sections of slides.
useSlide
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.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideRefs | ...number|string | Slide numbers (1-based), IDs, or tags. |
ppt.useSlide(1).useSlide(...slideRefs);
ppt.useSlide(1).useSlide(...slideRefs); // Fluent wrapper implementation
try {
ppt.useSlide(1).useSlide(...slideRefs);
} catch (err) {
console.error('API Error: ', err);
}
useAllSlides
Selects all slides.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).useAllSlides();
ppt.useSlide(1).useAllSlides(); // Fluent wrapper implementation
try {
ppt.useSlide(1).useAllSlides();
} catch (err) {
console.error('API Error: ', err);
}
addSlide
Adds a new slide to the presentation. Automatically generates required XML and relationship entries.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | NewSlideOptions | Slide definition. |
| [options.title] | string | Slide title text. |
| [options.layout] | string | Layout name to use (default: 'blank'). |
| [options.elements] | SlideElement[] | Elements to add to the slide. |
ppt.useSlide(1).addSlide(options = {});
ppt.useSlide(1).addSlide(options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).addSlide(options = {});
} catch (err) {
console.error('API Error: ', err);
}
cloneSlide
Clones an existing slide and appends it to the end (or at a position).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| sourceSlideNumber | number | 1-based source slide number. |
| [atPosition] | number | Optional position to insert (1-based). Default: append. |
ppt.useSlide(1).cloneSlide(sourceSlideNumber, atPosition);
ppt.useSlide(1).cloneSlide(sourceSlideNumber, atPosition); // Fluent wrapper implementation
try {
ppt.useSlide(1).cloneSlide(sourceSlideNumber, atPosition);
} catch (err) {
console.error('API Error: ', err);
}
removeSlide
Removes a slide from the presentation.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideNumber | number | 1-based slide number to remove. |
ppt.useSlide(1).removeSlide(slideNumber);
ppt.useSlide(1).removeSlide(slideNumber); // Fluent wrapper implementation
try {
ppt.useSlide(1).removeSlide(slideNumber);
} catch (err) {
console.error('API Error: ', err);
}
reorderSlides
Reorders slides in the presentation.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| order | number[] | Array of 1-based slide numbers in desired order. |
ppt.useSlide(1).reorderSlides(order);
ppt.useSlide(1).reorderSlides(order); // Fluent wrapper implementation
try {
ppt.useSlide(1).reorderSlides(order);
} catch (err) {
console.error('API Error: ', err);
}
tagSlide
Tags a slide with a custom string identifier for later selection.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideNumber | number | 1-based slide number. |
| tag | string | Custom tag string. |
ppt.useSlide(1).tagSlide(slideNumber, tag);
ppt.useSlide(1).tagSlide(slideNumber, tag); // Fluent wrapper implementation
try {
ppt.useSlide(1).tagSlide(slideNumber, tag);
} catch (err) {
console.error('API Error: ', err);
}
exportSlides
Exports selected slides to a new standalone PPTX engine. Useful for creating "slide decks" from a master template.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideNumbers | ...number | 1-based slide numbers to export. |
ppt.useSlide(1).exportSlides(...slideNumbers);
ppt.useSlide(1).exportSlides(...slideNumbers); // Fluent wrapper implementation
try {
ppt.useSlide(1).exportSlides(...slideNumbers);
} catch (err) {
console.error('API Error: ', err);
}
importSlideFrom
Imports a single slide from another PPTXTemplater instance into this presentation. Preserves all slide layouts, charts, relationships, and embedded media.
Source deck must be loaded first. Deduplicates layouts, media assets, and themes to prevent PowerPoint Repair Mode prompts.
Remaps slide-level relationships to root presentation indices, duplicates layout links, and copies media files into the target ZIP package.
| Parameter | Type | Description |
|---|---|---|
| sourceEngine | PPTXTemplater | Source PPTXTemplater instance. |
| slideRef | number|string | Slide index (1-based), ID, or custom tag. |
const source = await PPTXTemplater.load('template2.pptx');
await ppt.importSlideFrom(source, 1);
const source = await PPTXTemplater.load('slide_deck.pptx');
await ppt.useSlide(2).importSlideFrom(source, 'marketing-overview-slide');
const appendixDeck = await PPTXTemplater.load('appendix.pptx');
for (let i = 1; i <= appendixDeck.slideCount; i++) {
await ppt.importSlideFrom(appendixDeck, i);
}
importSlides
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.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndices | number[] | Array of 1-based slide indices to keep. |
ppt.useSlide(1).importSlides(slideIndices);
ppt.useSlide(1).importSlides(slideIndices); // Fluent wrapper implementation
try {
ppt.useSlide(1).importSlides(slideIndices);
} catch (err) {
console.error('API Error: ', err);
}
duplicateSlide
Duplicates an existing slide and inserts the copy at the specified position.
Index parameters are 1-based. Position index must fall between 1 and slideCount + 1.
Duplicates slide layout XML file, copies all elements relationships, and appends a slide reference entry inside `ppt/presentation.xml`.
| Parameter | Type | Description |
|---|---|---|
| slideIndex | number | 1-based index of the slide to duplicate. |
| [atPosition] | number | 1-based position to insert the copy. Defaults to end. |
ppt.duplicateSlide(1, 2);
// Duplicate slide 1 and insert at the end
const count = ppt.slideCount;
ppt.duplicateSlide(1, count + 1);
const items = await getPortfolioItems();
items.forEach((item, index) => {
ppt.duplicateSlide(2, 3 + index);
ppt.useSlide(3 + index)
.replaceTextByTag('title', item.title)
.replaceTextByTag('desc', item.description);
});
deleteSlide
Removes a slide from the presentation. Alias for `removeSlide()`.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndex | number | 1-based index of the slide to delete. |
ppt.useSlide(1).deleteSlide(slideIndex);
ppt.useSlide(1).deleteSlide(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).deleteSlide(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
moveSlide
Moves a slide from one position to another within the presentation.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| fromIndex | number | 1-based source slide index. |
| toIndex | number | 1-based target slide index. |
ppt.useSlide(1).moveSlide(fromIndex, toIndex);
ppt.useSlide(1).moveSlide(fromIndex, toIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).moveSlide(fromIndex, toIndex);
} catch (err) {
console.error('API Error: ', err);
}
insertSlide
Inserts a new blank slide at the specified position.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndex | number | 1-based position to insert the slide at. |
| [options] | Object | Insert options. |
| [options.layoutIndex] | number | Slide layout index to apply. |
ppt.useSlide(1).insertSlide(slideIndex, options = {});
ppt.useSlide(1).insertSlide(slideIndex, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).insertSlide(slideIndex, options = {});
} catch (err) {
console.error('API Error: ', err);
}
getSlides
Returns an array of all slides in the presentation with their metadata.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getSlides();
ppt.useSlide(1).getSlides(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getSlides();
} catch (err) {
console.error('API Error: ', err);
}
Text API
Execute text tag replacements, un-fragment text runs, search string tags, and apply links.
replaceText
Replaces template placeholders (e.g., {{key}}) with values in the selected slides. Works inside text boxes, titles, grouped shapes, tables, and shapes.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| replacements | Object.<string, string> | Map of placeholder → replacement value. |
ppt.useSlide(1).replaceText(replacements);
ppt.useSlide(1).replaceText(replacements); // Fluent wrapper implementation
try {
ppt.useSlide(1).replaceText(replacements);
} catch (err) {
console.error('API Error: ', err);
}
addHyperlink
Adds or replaces a hyperlink on a text run or shape.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | HyperlinkOptions | Hyperlink configuration. |
| options.text | string | Text to find and make clickable. |
| options.url | string | Target URL. |
| [options.tooltip] | string | Optional tooltip. |
ppt.useSlide(1).addHyperlink(options);
ppt.useSlide(1).addHyperlink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addHyperlink(options);
} catch (err) {
console.error('API Error: ', err);
}
addSlideLink
Adds an inter-slide hyperlink to a specific text element.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | Object | Link configuration. |
| options.sourceSlide | number | Source slide number (1-based). |
| options.targetSlide | number | Destination slide number (1-based). |
| options.element | string | Text element to make clickable. |
ppt.useSlide(1).addSlideLink(options);
ppt.useSlide(1).addSlideLink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addSlideLink(options);
} catch (err) {
console.error('API Error: ', err);
}
addImageLink
Adds an inter-slide hyperlink to an image.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.slide | number | Source slide number. |
| options.imageId | string | Image name/id to make clickable. |
| options.targetSlide | number | Destination slide number. |
ppt.useSlide(1).addImageLink(options);
ppt.useSlide(1).addImageLink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addImageLink(options);
} catch (err) {
console.error('API Error: ', err);
}
addShapeLink
Adds an inter-slide hyperlink to a shape.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.slide | number | Source slide number. |
| options.shapeId | string | Shape name/id to make clickable. |
| options.targetSlide | number | Destination slide number. |
ppt.useSlide(1).addShapeLink(options);
ppt.useSlide(1).addShapeLink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addShapeLink(options);
} catch (err) {
console.error('API Error: ', err);
}
addTextNavigationLink
Adds a special navigation link (next, previous, first, last slide) to a text element.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.slide | number | Source slide number (1-based). |
| options.element | string | Text element to make clickable. |
| options.action | 'next'|'previous'|'first'|'last' | Navigation action type. |
ppt.useSlide(1).addTextNavigationLink(options);
ppt.useSlide(1).addTextNavigationLink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addTextNavigationLink(options);
} catch (err) {
console.error('API Error: ', err);
}
addShapeNavigationLink
Adds a special navigation link (next, previous, first, last slide) to a shape or image.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| options | Object | |
| options.slide | number | Source slide number (1-based). |
| options.shapeId | string | Shape name/id to make clickable. |
| options.action | 'next'|'previous'|'first'|'last' | Navigation action type. |
ppt.useSlide(1).addShapeNavigationLink(options);
ppt.useSlide(1).addShapeNavigationLink(options); // Fluent wrapper implementation
try {
ppt.useSlide(1).addShapeNavigationLink(options);
} catch (err) {
console.error('API Error: ', err);
}
updateText
Updates shape text or list content by placeholder tag or shape name/ID. Supports bullet lists, numbered lists, nested lists, and custom styling. / /** Updates text content or list items in a named shape or text box. Supports plain strings, bullet lists, numbered lists, and nested lists.
Supports simple strings or bulleted/numbered list config objects. Paragraph alignments and styles of template run are preserved.
Replaces paragraph text run content or spawns multiple <a:p> sibling blocks formatted with bullet and numbering markers.
| Parameter | Type | Description |
|---|---|---|
| tag | string | Placeholder tag (e.g. '{{name}}' or 'name') or shape name/ID. |
| data | string|Object | String value or list configuration object. |
| tag | string | Shape name/ID or placeholder tag. |
| data | string|Object | Text string, or list configuration object. |
ppt.useSlide(1).updateText('Features', {
list: ['Point A', 'Point B', 'Point C']
});
// Numbered and nested lists
ppt.useSlide(1).updateText('Steps', {
ordered: true,
list: [
'Phase 1',
{ text: 'Phase 2', children: ['Sub-step A', 'Sub-step B'] }
]
});
// Full styled and customized list structure
ppt.useSlide(2).updateText('KPIs', {
list: ['Revenue Up', 'Margins Normal'],
style: {
fontSize: 18,
color: '#0055AA',
bulletColor: '#FF5500',
bulletChar: '✦'
}
});
getList
Retrieves list items from a shape or text box by name or placeholder tag. / /** Retrieves list items from a shape or text box.
Scans specified shape or text placeholders, parsing nested levels and bullet definitions.
Reads individual paragraph structures, properties (a:pPr lvl), and combined run texts from shape text frames.
| Parameter | Type | Description |
|---|---|---|
| tag | string | Shape name/ID or placeholder tag. |
| tag | string | Shape name/ID or placeholder tag. |
const items = ppt.useSlide(1).getList('Features');
console.log(items); // ['A', { text: 'B', children: [...] }]
const items = ppt.getList('Steps');
try {
const list = ppt.useSlide(1).getList('ProjectRequirements');
list.forEach(item => {
const text = typeof item === 'string' ? item : item.text;
console.log('List Item:', text);
});
} catch (err) {
console.error('Failed to parse list:', err);
}
validateList
Validates a list structure and values.
Verifies level indices (0-8), level skipping (gaps), and formatting parameters.
Performs dry-run syntax and structure audits without writing adjustments to disk.
| Parameter | Type | Description |
|---|---|---|
| data | Object|Array | List config object or array of items. |
const result = ppt.validateList(['Valid string', 'Another item']);
console.log(result.valid);
const report = ppt.validateList({
list: ['Parent', { text: 'Child', children: ['Grandchild'] }],
style: { fontSize: -10 } // will fail validation
});
console.log(report.errors);
const check = ppt.validateList(userProvidedListData);
if (!check.valid) {
console.warn('Formatting issues:', check.errors.join('\n'));
}
replaceTextByTag
Replaces a text placeholder tag across all targeted shapes on selected slides. Finds shapes containing `{{tag}}` or `tag` and replaces the placeholder value.
Tags split across multiple text runs are healed before replacements. Standard layout handles exact matches.
Merges fragmented `<a:r>` runs inside text paragraphs and replaces string values while preserving run font parameters.
| Parameter | Type | Description |
|---|---|---|
| tag | string | Placeholder tag name (e.g. `'{{name}}'` or `'name'`). |
| value | string | Replacement value. |
| [options] | Object | Options. |
| [options.slide] | number | Target a specific slide index (overrides `useSlide`). |
ppt.useSlide(1).replaceTextByTag('company', 'Acme Corp');
// Search-replace with custom text configuration
ppt.useSlide(1).replaceTextByTag('year', '2026', { bold: true });
const profile = await getUserProfile();
ppt.useSlide(1)
.replaceTextByTag('firstName', profile.first)
.replaceTextByTag('lastName', profile.last)
.replaceTextByTag('email', profile.email);
replaceMultiple
Replaces multiple text placeholder tags in a single pass. More efficient than calling `replaceTextByTag()` repeatedly.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| replacements | Object<string, string> | Map of `{ tag: value }` pairs. |
| [options] | Object | Options (same as `replaceTextByTag`). |
ppt.useSlide(1).replaceMultiple(replacements, options = {});
ppt.useSlide(1).replaceMultiple(replacements, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).replaceMultiple(replacements, options = {});
} catch (err) {
console.error('API Error: ', err);
}
findText
Searches for all occurrences of a text string across the targeted slides.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| text | string | Text to search for. |
ppt.useSlide(1).findText(text);
ppt.useSlide(1).findText(text); // Fluent wrapper implementation
try {
ppt.useSlide(1).findText(text);
} catch (err) {
console.error('API Error: ', err);
}
getTextElements
Returns all text elements (paragraphs) across the targeted slides.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getTextElements();
ppt.useSlide(1).getTextElements(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getTextElements();
} catch (err) {
console.error('API Error: ', err);
}
Images API
Add images dynamically, swap templates, and extract file lists.
replaceImage
Replaces an existing image in the presentation by shape name or relationship ID.
Image placeholder name/id must exist in template. Image types must match or content-type overrides must be registered.
Overwrites target media target inside presentation archive or updates relationship mapping target references to point to the new image.
| Parameter | Type | Description |
|---|---|---|
| imageIdOrName | string | Shape name, alt text, or relationship ID of the image. |
| sourcePathOrBuffer | string|Buffer | Path to the replacement image file, or a Buffer. |
await ppt.useSlide(1).replaceImage('logo-img', './new-logo.png');
// Pass a binary buffer
const imgBuffer = fs.readFileSync('avatar.jpg');
await ppt.useSlide(1).replaceImage('profile-avatar', imgBuffer);
const users = await getTeamMembers();
for (let i = 0; i < users.length; i++) {
const user = users[i];
const avatarBuffer = await fetchAvatar(user.id);
ppt.useSlide(2 + i);
await ppt.replaceImage('user-avatar', avatarBuffer);
}
addImage
Adds a new image to the targeted slide(s) at the specified position.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| sourcePathOrBuffer | string|Buffer | Path to the image file, or a Buffer. |
| [options] | Object | Positioning and display options. |
| [options.x] | number | X offset in EMUs (1 inch = 914,400 EMUs). |
| [options.y] | number | Y offset in EMUs. |
| [options.width] | number | Width in EMUs. |
| [options.height] | number | Height in EMUs. |
| [options.rotation] | number | Rotation in degrees (0–360). |
| [options.opacity] | number | Opacity (0–100). |
| [options.name] | string | Shape name for the image. |
| [options.cropTo] | Object | Crop percentages `{ l, r, t, b }` (0–100000). |
ppt.useSlide(1).addImage(sourcePathOrBuffer, options = {});
ppt.useSlide(1).addImage(sourcePathOrBuffer, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).addImage(sourcePathOrBuffer, options = {});
} catch (err) {
console.error('API Error: ', err);
}
removeImage
Removes an image from the targeted slide(s) by shape name or relationship ID.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| imageIdOrName | string | Shape name, alt text, or relationship ID of the image. |
ppt.useSlide(1).removeImage(imageIdOrName);
ppt.useSlide(1).removeImage(imageIdOrName); // Fluent wrapper implementation
try {
ppt.useSlide(1).removeImage(imageIdOrName);
} catch (err) {
console.error('API Error: ', err);
}
getImages
Returns metadata for all images found on the targeted slide(s).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getImages();
ppt.useSlide(1).getImages(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getImages();
} catch (err) {
console.error('API Error: ', err);
}
Shapes API
Modify text within shapes, clone layout blocks, and delete shapes.
updateShapeText
Sets the text content of an existing shape by name or ID.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | Shape name or ID. |
| text | string | New text content. |
ppt.useSlide(1).updateShapeText(shapeId, text);
ppt.useSlide(1).updateShapeText(shapeId, text); // Fluent wrapper implementation
try {
ppt.useSlide(1).updateShapeText(shapeId, text);
} catch (err) {
console.error('API Error: ', err);
}
updateShapePosition
Updates the position and/or dimensions of an existing shape on targeted slides.
Coordinate offsets are in English Metric Units (EMU). Properties omitted are not modified.
Updates the coordinate values in the shape `<a:off>` and `<a:ext>` tags inside the slide XML.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | |
| options | Object | |
| [options.x] | number | |
| [options.y] | number | |
| [options.width] | number | |
| [options.height] | number |
ppt.useSlide(1).updateShapePosition('TitleShape', { x: 1000000, y: 1500000 });
ppt.updateShapePosition('TextBoxName', {
x: 2000000,
y: 3000000,
width: 4000000,
height: 500000
});
// Relocate a shape dynamically based on slide width
const slideWidth = 12192000;
ppt.useSlide(1).updateShapePosition('Sidebar', {
x: slideWidth - 3000000,
width: 2500000
});
updateTextBoxPosition
Updates the position and/or dimensions of an existing textbox on targeted slides.
Coordinate offsets are in English Metric Units (EMU). Properties omitted are not modified.
Updates the coordinate values in the textbox shape `<a:off>` and `<a:ext>` tags inside the slide XML.
| Parameter | Type | Description |
|---|---|---|
| textBoxId | string | |
| options | Object | |
| [options.x] | number | |
| [options.y] | number | |
| [options.width] | number | |
| [options.height] | number |
ppt.useSlide(1).updateTextBoxPosition('TextBox 2', { x: 1000000, y: 1500000 });
ppt.updateTextBoxPosition('TextBox 2', {
x: 2000000,
y: 3000000,
width: 4000000,
height: 500000
});
// Relocate a textbox dynamically based on slide width
const slideWidth = 12192000;
ppt.useSlide(1).updateTextBoxPosition('StatusBox', {
x: slideWidth - 3000000,
width: 2500000
});
cloneShape
Duplicates an existing shape with a new ID, optionally at a different position.
Offsets are in English Metric Units (EMU). Offset parameters specify position displacement.
Duplicates the target shape element XML node (`p:sp`) and adds positioning coordinates.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | Source shape name or ID. |
| newShapeId | string | Name/ID for the cloned shape. |
| [options] | Object | Position overrides for the clone. |
| [options.x] | number | X offset for the clone (EMUs). |
| [options.y] | number | Y offset for the clone (EMUs). |
ppt.useSlide(1).cloneShape('card-bg', 'card-bg-2');
// Clone with specific displacement offsets
ppt.useSlide(1).cloneShape('card-bg', 'card-bg-2', {
offsetX: 360000, // 360,000 EMUs = ~1 inch
offsetY: 0
});
const items = ['Speed', 'Stability', 'Scalability'];
items.forEach((item, index) => {
if (index > 0) {
ppt.cloneShape('bullet-template', `bullet-${index}`, {
offsetX: 0,
offsetY: index * 400000
}).updateShapeText(`bullet-${index}`, item);
} else {
ppt.updateShapeText('bullet-template', item);
}
});
deleteShape
Removes a shape from the targeted slide(s). Alias for `removeShape()`.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | Shape name or ID to delete. |
ppt.useSlide(1).deleteShape(shapeId);
ppt.useSlide(1).deleteShape(shapeId); // Fluent wrapper implementation
try {
ppt.useSlide(1).deleteShape(shapeId);
} catch (err) {
console.error('API Error: ', err);
}
getShapes
Returns metadata for all shapes on the targeted slide(s).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getShapes();
ppt.useSlide(1).getShapes(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getShapes();
} catch (err) {
console.error('API Error: ', err);
}
validateShape
Validates shape options configuration.
Validates configuration parameters without modifying document. Checks shape types, colors, and dimensions.
None. Does not touch slide XML.
| Parameter | Type | Description |
|---|---|---|
| options | Object |
const errors = ppt.validateShape(shapeOptions);
const errors = ppt.validateShape({
id: 'card',
type: 'rectangle',
fill: 'red' // Invalid format
});
if (errors.length > 0) {
console.error('Errors:', errors);
}
// Run configuration validation check before addition
const config = getShapeConfig();
const errors = ppt.validateShape(config);
if (errors.length === 0) {
await ppt.addShape(config);
} else {
throw new Error('Config invalid: ' + errors.join(', '));
}
addShape
Adds a new shape to the targeted slide(s).
Dimensions/coordinates are converted where 1 pixel ≈ 9525 EMUs. Supports shapes: rectangle, square, circle, ellipse, roundedRectangle.
Creates and appends a `<p:sp>` shape tree node under `<p:spTree>` and updates Z-ordering list.
| Parameter | Type | Description |
|---|---|---|
| typeOrOptions | string|Object | |
| [options={}] | Object |
await ppt.useSlide(1).addShape({
type: 'rectangle',
id: 'sales-box',
x: 100,
y: 100,
width: 200,
height: 100,
fill: '#2563EB'
});
// Create rounded rectangle with text and gradient fill
await ppt.addShape({
type: 'roundedRectangle',
id: 'card',
x: 100,
y: 100,
width: 300,
height: 120,
borderRadius: 20,
fill: {
type: 'gradient',
colors: ['#2563EB', '#7C3AED']
},
text: 'Revenue Growth',
textStyle: { fontSize: 18, bold: true, color: '#FFFFFF', align: 'center' }
});
// Dynamically add card shapes on slide
for (const [i, metric] of metrics.entries()) {
await ppt.addShape({
type: 'roundedRectangle',
id: `metric-card-${i}`,
x: 50 + i * 250,
y: 150,
width: 200,
height: 120,
borderRadius: 10,
fill: '#FFFFFF',
border: { color: '#E2E8F0', width: 2 },
text: metric.name + '\n' + metric.value,
textStyle: { fontSize: 14, color: '#1E293B', align: 'center' }
});
}
updateShape
Updates an existing shape in-place.
Dimensions/coordinates are converted where 1 pixel ≈ 9525 EMUs. Properties not specified are preserved.
Updates shape geometry attributes, fills, borders, text body values, or shadows in slide XML in-place.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | |
| options | Object |
await ppt.useSlide(1).updateShape('sales-box', { fill: '#10B981' });
await ppt.updateShape('sales-box', {
x: 200,
y: 300,
width: 400,
height: 120,
border: { color: '#EF4444', width: 3 },
text: 'Updated Revenue'
});
// Toggle alert shapes color based on performance threshold
if (growthRate < 0) {
await ppt.updateShape('AlertBox', {
fill: '#EF4444',
text: 'Critical Drop Detected'
});
} else {
await ppt.updateShape('AlertBox', {
fill: '#10B981',
text: 'Stable Growth'
});
}
removeShape
Removes a shape from the targeted slide(s).
Removes target shape by shape ID or template name across slide canvas. Synchronizes Z-order list.
Deletes `<p:sp>` element from the shape tree and filters its ID out of the Z-ordering list.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string |
await ppt.useSlide(1).removeShape('sales-box');
await ppt.removeShape('sales-box');
// Remove template shapes if option is disabled
if (!showDashboardKPIs) {
const kpiIds = ['KpiCard1', 'KpiCard2', 'KpiCard3'];
for (const id of kpiIds) {
try {
await ppt.removeShape(id);
} catch (e) {
// Shape not present
}
}
}
getShape
Discovers and retrieves details of an existing shape on the targeted slides.
Returns shape details mapping EMU back to pixel coordinates. Preset geometries mapped back to user-facing types.
Reads XML shape nodes and coordinates to return JS representation.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string |
const shape = ppt.getShape('sales-box');
const shape = ppt.useSlide(1).getShape('sales-box');
if (shape) {
console.log(`Shape is at x:${shape.x}, y:${shape.y}`);
}
// Auto-align shapes dynamically
const card = ppt.getShape('BaseCard');
if (card) {
await ppt.addShape({
type: 'rectangle',
id: 'AdjacentCard',
x: card.x + card.width + 20,
y: card.y,
width: card.width,
height: card.height
});
}
alignShapeToCell
Aligns an existing shape to a table cell's position.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| shapeId | string | Unique shape name/id in the template. |
| tableIdOrObj | string|Object | Table ID string, or table object. |
| rowIndex | number | 0-based row index. |
| colIndex | number | 0-based column index. |
| [options] | Object | Alignment options. |
| [options.horizontal='center'] | 'left'|'center'|'right' | Horizontal alignment. |
| [options.vertical='middle'] | 'top'|'middle'|'bottom' | Vertical alignment. |
ppt.useSlide(1).alignShapeToCell(shapeId, tableIdOrObj, rowIndex, colIndex, options = {});
ppt.useSlide(1).alignShapeToCell(shapeId, tableIdOrObj, rowIndex, colIndex, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).alignShapeToCell(shapeId, tableIdOrObj, rowIndex, colIndex, options = {});
} catch (err) {
console.error('API Error: ', err);
}
Layer Stacking (Z-Order)
Manage elements stack sorting (Bring Forward, Send to Back) within presentation slide trees.
bringForward
Moves slide element one layer forward.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).bringForward(optionsOrId);
ppt.useSlide(1).bringForward(optionsOrId); // Fluent wrapper implementation
try {
ppt.useSlide(1).bringForward(optionsOrId);
} catch (err) {
console.error('API Error: ', err);
}
sendBackward
Moves slide element one layer backward.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).sendBackward(optionsOrId);
ppt.useSlide(1).sendBackward(optionsOrId); // Fluent wrapper implementation
try {
ppt.useSlide(1).sendBackward(optionsOrId);
} catch (err) {
console.error('API Error: ', err);
}
bringToFront
Moves slide element above all other objects.
Object ID or name must match an element on slide canvas. No-op if object is already topmost.
Reorders slide element nodes under `<p:spTree>`, moving the matched node to the end of the tag sequence list.
ppt.useSlide(1).bringToFront('OverlayLogo');
// Or pass as config object directly
ppt.bringToFront({ slide: 1, objectId: 'OverlayLogo' });
// Bring all images to the front
const layers = ppt.getObjectOrder(1);
layers.forEach(lay => {
if (lay.type === 'image') {
ppt.bringToFront(lay.id);
}
});
sendToBack
Moves slide element behind all other objects.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).sendToBack(optionsOrId);
ppt.useSlide(1).sendToBack(optionsOrId); // Fluent wrapper implementation
try {
ppt.useSlide(1).sendToBack(optionsOrId);
} catch (err) {
console.error('API Error: ', err);
}
setZIndex
Moves slide element to the specific 1-based stacking position.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).setZIndex(optionsOrId, zIndex);
ppt.useSlide(1).setZIndex(optionsOrId, zIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).setZIndex(optionsOrId, zIndex);
} catch (err) {
console.error('API Error: ', err);
}
moveObjectBefore
Moves slide element directly before (below) a target element.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).moveObjectBefore(optionsOrId, targetId);
ppt.useSlide(1).moveObjectBefore(optionsOrId, targetId); // Fluent wrapper implementation
try {
ppt.useSlide(1).moveObjectBefore(optionsOrId, targetId);
} catch (err) {
console.error('API Error: ', err);
}
moveObjectAfter
Moves slide element directly after (above) a target element.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).moveObjectAfter(optionsOrId, targetId);
ppt.useSlide(1).moveObjectAfter(optionsOrId, targetId); // Fluent wrapper implementation
try {
ppt.useSlide(1).moveObjectAfter(optionsOrId, targetId);
} catch (err) {
console.error('API Error: ', err);
}
reorderObjects
Reorders slide objects exactly as specified in the array.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).reorderObjects(optionsOrOrder);
ppt.useSlide(1).reorderObjects(optionsOrOrder); // Fluent wrapper implementation
try {
ppt.useSlide(1).reorderObjects(optionsOrOrder);
} catch (err) {
console.error('API Error: ', err);
}
getObjectOrder
Gets the ordered metadata of all objects on the slide. / /** Returns an ordered array of all slide objects (shapes, images, charts, tables) from bottom to top of the stacking order.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [slideIndex] | number | 1-based slide index. Defaults to the active slide. |
ppt.useSlide(1).getObjectOrder(slideIndex);
ppt.useSlide(1).getObjectOrder(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).getObjectOrder(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
applyZOrder
Applies bulk template configurations for slide elements stacking layers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).applyZOrder(slideOrConfigs, configsOption);
ppt.useSlide(1).applyZOrder(slideOrConfigs, configsOption); // Fluent wrapper implementation
try {
ppt.useSlide(1).applyZOrder(slideOrConfigs, configsOption);
} catch (err) {
console.error('API Error: ', err);
}
getTopMostObject
Retrieves the info of the top-most object on the slide. / /** Returns the top-most (front) object on the slide.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [slideIndex] | number | 1-based slide index. Defaults to the active slide. |
ppt.useSlide(1).getTopMostObject(slideIndex);
ppt.useSlide(1).getTopMostObject(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).getTopMostObject(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
getBottomMostObject
Retrieves the info of the bottom-most object on the slide. / /** Returns the bottom-most (back) object on the slide.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [slideIndex] | number | 1-based slide index. Defaults to the active slide. |
ppt.useSlide(1).getBottomMostObject(slideIndex);
ppt.useSlide(1).getBottomMostObject(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).getBottomMostObject(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
swapObjects
Swaps stacking positions of two slide objects. / /** Swaps the stacking positions of two slide objects.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndexOrId1 | number|string | Slide index (if 3 args) or first object ID (if 2 args). |
| id1OrId2 | string | First object ID (if 3 args) or second object ID (if 2 args). |
| [id2] | string | Second object ID (only if slide index is provided as first arg). |
ppt.useSlide(1).swapObjects(slideIndexOrId1, id1OrId2, id2);
ppt.useSlide(1).swapObjects(slideIndexOrId1, id1OrId2, id2); // Fluent wrapper implementation
try {
ppt.useSlide(1).swapObjects(slideIndexOrId1, id1OrId2, id2);
} catch (err) {
console.error('API Error: ', err);
}
sortObjects
Sorts stacking order using a custom comparison function. / /** Sorts all slide objects using a custom comparison function.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndexOrCompareFn | number|Function | Slide index (if 2 args) or compare function (if 1 arg). |
| [compareFnOption] | Function | Compare function when slide index is provided. |
ppt.useSlide(1).sortObjects(slideIndexOrCompareFn, compareFnOption);
ppt.useSlide(1).sortObjects(slideIndexOrCompareFn, compareFnOption); // Fluent wrapper implementation
try {
ppt.useSlide(1).sortObjects(slideIndexOrCompareFn, compareFnOption);
} catch (err) {
console.error('API Error: ', err);
}
normalizeZOrder
Cleans up and normalizes stacking order consistency. / /** Normalizes the stacking order of all objects on a slide, removing gaps and ensuring Z-index values are sequential (1, 2, 3, ...).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [slideIndex] | number | 1-based slide index. Defaults to the active slide. |
ppt.useSlide(1).normalizeZOrder(slideIndex);
ppt.useSlide(1).normalizeZOrder(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).normalizeZOrder(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
Utilities & Validation
Load files, inspect XML elements, validation checks, and repair ZIP packages.
const
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
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).const();
ppt.useSlide(1).const(); // Fluent wrapper implementation
try {
ppt.useSlide(1).const();
} catch (err) {
console.error('API Error: ', err);
}
class
No description available.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).class();
ppt.useSlide(1).class(); // Fluent wrapper implementation
try {
ppt.useSlide(1).class();
} catch (err) {
console.error('API Error: ', err);
}
static
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.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| source | string|Buffer | Path to PPTX file or Buffer containing PPTX data. |
ppt.useSlide(1).static();
ppt.useSlide(1).static(); // Fluent wrapper implementation
try {
ppt.useSlide(1).static();
} catch (err) {
console.error('API Error: ', err);
}
enablePerformanceProfile
Enables internal performance profiling. After calling this, use `getPerformanceMetrics()` to read timing data.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).enablePerformanceProfile();
ppt.useSlide(1).enablePerformanceProfile(); // Fluent wrapper implementation
try {
ppt.useSlide(1).enablePerformanceProfile();
} catch (err) {
console.error('API Error: ', err);
}
enableDebug
Enables debug-level logging for this session. Shortcut for `PPTXTemplater.setLogLevel('debug')`.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).enableDebug();
ppt.useSlide(1).enableDebug(); // Fluent wrapper implementation
try {
ppt.useSlide(1).enableDebug();
} catch (err) {
console.error('API Error: ', err);
}
getPerformanceMetrics
Returns performance metrics collected since `enablePerformanceProfile()` was called. Includes timing for template load, XML parse, chart update, image update, ZIP generation, total elapsed time, and memory usage. `imageUpdateMs`, `zipGenerationMs`, `totalMs`, `memoryUsedMB`.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getPerformanceMetrics();
ppt.useSlide(1).getPerformanceMetrics(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getPerformanceMetrics();
} catch (err) {
console.error('API Error: ', err);
}
getInfo
Returns presentation metadata (title, author, slide count, etc.)
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).getInfo();
ppt.useSlide(1).getInfo(); // Fluent wrapper implementation
try {
ppt.useSlide(1).getInfo();
} catch (err) {
console.error('API Error: ', err);
}
validate
Validates the XML structure of the current PPTX. Reports issues with relationship IDs, missing parts, etc.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).validate();
ppt.useSlide(1).validate(); // Fluent wrapper implementation
try {
ppt.useSlide(1).validate();
} catch (err) {
console.error('API Error: ', err);
}
repair
Repairs corrupted OpenXML structure, relationships, and content types. Removes orphan relationships, rebuilds slide references, and fixes missing entries.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).repair();
ppt.useSlide(1).repair(); // Fluent wrapper implementation
try {
ppt.useSlide(1).repair();
} catch (err) {
console.error('API Error: ', err);
}
debugRelationships
Logs all relationships across the presentation to the console for debugging.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).debugRelationships();
ppt.useSlide(1).debugRelationships(); // Fluent wrapper implementation
try {
ppt.useSlide(1).debugRelationships();
} catch (err) {
console.error('API Error: ', err);
}
inspectSlide
Inspects a specific slide's structure and relationships.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndex | number | 1-based slide index. |
ppt.useSlide(1).inspectSlide(slideIndex);
ppt.useSlide(1).inspectSlide(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).inspectSlide(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
inspectXML
Inspects and logs the raw XML of any file in the ZIP.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| xmlPath | string | Path inside the ZIP (e.g., 'ppt/slides/slide1.xml') |
ppt.useSlide(1).inspectXML(xmlPath);
ppt.useSlide(1).inspectXML(xmlPath); // Fluent wrapper implementation
try {
ppt.useSlide(1).inspectXML(xmlPath);
} catch (err) {
console.error('API Error: ', err);
}
inspectChart
Inspects a specific chart's metadata and structure.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| chartId | string |
ppt.useSlide(1).inspectChart(chartId);
ppt.useSlide(1).inspectChart(chartId); // Fluent wrapper implementation
try {
ppt.useSlide(1).inspectChart(chartId);
} catch (err) {
console.error('API Error: ', err);
}
inspectChartXML
Inspects and logs the raw XML of a chart file.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| chartFileName | string |
ppt.useSlide(1).inspectChartXML(chartFileName);
ppt.useSlide(1).inspectChartXML(chartFileName); // Fluent wrapper implementation
try {
ppt.useSlide(1).inspectChartXML(chartFileName);
} catch (err) {
console.error('API Error: ', err);
}
debugChartRelationships
Logs all chart relationships.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).debugChartRelationships();
ppt.useSlide(1).debugChartRelationships(); // Fluent wrapper implementation
try {
ppt.useSlide(1).debugChartRelationships();
} catch (err) {
console.error('API Error: ', err);
}
saveToFile
Saves the modified PPTX to a file on disk.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| filePath | string | Output file path. |
| [options] | Object | Save options. |
| [options.strict=false] | boolean | Throw error on validation failure. |
ppt.useSlide(1).saveToFile(filePath, options = {});
ppt.useSlide(1).saveToFile(filePath, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).saveToFile(filePath, options = {});
} catch (err) {
console.error('API Error: ', err);
}
save
Saves the presentation. Equivalent to saveToFile.
Identical to saveToFile. Saves the modified PPTX to a file path.
Serializes presentation XML structure and packages all elements into target ZIP package on disk.
| Parameter | Type | Description |
|---|---|---|
| filePath | string | Output file path. |
| [options] | Object | Save options. |
await ppt.save('output.pptx');
await ppt.save('output.pptx', { strict: true });
await ppt.save('/path/to/output.pptx');
saveXml
Saves the modified presentation XML structures directly to a folder.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| folderPath | string | Target directory path. |
ppt.useSlide(1).saveXml(folderPath);
ppt.useSlide(1).saveXml(folderPath); // Fluent wrapper implementation
try {
ppt.useSlide(1).saveXml(folderPath);
} catch (err) {
console.error('API Error: ', err);
}
saveToFolder
Saves the modified presentation XML structures directly to a folder.
Ensures the output directory exists, creating parent directories if needed. Overwrites any existing files in that folder.
Writes the modified OpenXML files and resources directly to disk in their uncompressed folder structure.
| Parameter | Type | Description |
|---|---|---|
| folderPath | string | Target directory path. |
await ppt.saveToFolder('./output-template');
await ppt.saveXml('./output-template'); // Alias method
try {
await ppt.saveToFolder('/var/www/output-template');
console.log('Saved uncompressed presentation files to disk');
} catch (err) {
console.error('Failed to save to folder:', err);
}
toBuffer
Returns the PPTX content as a Node.js Buffer.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [options] | Object | Save options. |
ppt.useSlide(1).toBuffer(options = {});
ppt.useSlide(1).toBuffer(options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).toBuffer(options = {});
} catch (err) {
console.error('API Error: ', err);
}
toStream
Returns the PPTX content as a readable Node.js Stream.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [options] | Object | Save options. |
ppt.useSlide(1).toStream(options = {});
ppt.useSlide(1).toStream(options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).toStream(options = {});
} catch (err) {
console.error('API Error: ', err);
}
saveToStream
Saves the presentation to a readable stream or pipes it to a writable stream.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| [writableOrOptions] | NodeJS.WritableStream|Object | Writable stream to pipe to, or options object. |
| [options] | Object | Save options if writable stream was passed first. |
ppt.useSlide(1).saveToStream(writableOrOptions, options = {});
ppt.useSlide(1).saveToStream(writableOrOptions, options = {}); // Fluent wrapper implementation
try {
ppt.useSlide(1).saveToStream(writableOrOptions, options = {});
} catch (err) {
console.error('API Error: ', err);
}
validatePresentation
Performs a comprehensive validation of the entire PPTX structure. Checks slide XML, relationships, content types, slide masters, and layouts.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).validatePresentation();
ppt.useSlide(1).validatePresentation(); // Fluent wrapper implementation
try {
ppt.useSlide(1).validatePresentation();
} catch (err) {
console.error('API Error: ', err);
}
validatePresentationXml
Performs validation specifically on PowerPoint XML folder contents/relationships.
Performs deep structural relationship verification of folders. Ignores external URLs.
Dry-runs verification of content types overrides, slide layouts, and master configurations.
const report = await ppt.validatePresentationXml();
if (!report.valid) console.error(report.errors);
const report = await ppt.validatePresentationXml();
expect(report.valid).toBe(true);
const check = await ppt.validatePresentationXml();
if (!check.valid) {
throw new Error('Presentation XML validation failed:\n' + check.errors.join('\n'));
}
validateSlide
Validates the XML structure of a specific slide.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| slideIndex | number | 1-based slide index to validate. |
ppt.useSlide(1).validateSlide(slideIndex);
ppt.useSlide(1).validateSlide(slideIndex); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateSlide(slideIndex);
} catch (err) {
console.error('API Error: ', err);
}
validateTable
Validates the XML structure of a specific table on the active slide.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| tableId | string | Table name or shape ID. |
ppt.useSlide(1).validateTable(tableId);
ppt.useSlide(1).validateTable(tableId); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateTable(tableId);
} catch (err) {
console.error('API Error: ', err);
}
validateArchive
Validates the internal ZIP archive structure of the PPTX file. Checks that all files referenced in the archive are accessible and uncorrupted. Throws if critical structural issues are found.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).validateArchive();
ppt.useSlide(1).validateArchive(); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateArchive();
} catch (err) {
console.error('API Error: ', err);
}
enableDebugZip
Enables ZIP debug output. When enabled, every call to `toBuffer()` or `toStream()` will log all ZIP entries (name, compression method, sizes, CRC).
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).enableDebugZip();
ppt.useSlide(1).enableDebugZip(); // Fluent wrapper implementation
try {
ppt.useSlide(1).enableDebugZip();
} catch (err) {
console.error('API Error: ', err);
}
validateRelationships
Validates relationships for a specific part path inside the ZIP.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| partPath | string | ZIP path to validate (e.g. `'ppt/slides/slide1.xml'`). |
ppt.useSlide(1).validateRelationships(partPath);
ppt.useSlide(1).validateRelationships(partPath); // Fluent wrapper implementation
try {
ppt.useSlide(1).validateRelationships(partPath);
} catch (err) {
console.error('API Error: ', err);
}
slideCount
Returns the total number of slides in the loaded presentation. @type {number}
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).slideCount();
ppt.useSlide(1).slideCount(); // Fluent wrapper implementation
try {
ppt.useSlide(1).slideCount();
} catch (err) {
console.error('API Error: ', err);
}
function
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.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
| Parameter | Type | Description |
|---|---|---|
| existingIds | string[] | Array of existing rId strings (e.g., ['rId1', 'rId2']). |
ppt.useSlide(1).function();
ppt.useSlide(1).function(); // Fluent wrapper implementation
try {
ppt.useSlide(1).function();
} catch (err) {
console.error('API Error: ', err);
}
setLogLevel
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).setLogLevel(());
ppt.useSlide(1).setLogLevel(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).setLogLevel(());
} catch (err) {
console.error('API Error: ', err);
}
preload
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).preload(());
ppt.useSlide(1).preload(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).preload(());
} catch (err) {
console.error('API Error: ', err);
}
cache
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).cache(());
ppt.useSlide(1).cache(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).cache(());
} catch (err) {
console.error('API Error: ', err);
}
fromCache
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).fromCache(());
ppt.useSlide(1).fromCache(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).fromCache(());
} catch (err) {
console.error('API Error: ', err);
}
clearCache
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).clearCache(());
ppt.useSlide(1).clearCache(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).clearCache(());
} catch (err) {
console.error('API Error: ', err);
}
fromPresentationXml
Delegates core actions to slide element sub-managers.
The directory root must contain valid OpenXML structural subdirectories like ppt/ and _rels/. If presentation.xml cannot be found under the resolved root, it throws PPTXError.
Reads XML files directly from disk without decompressing a ZIP file.
const ppt = await PPTXTemplate.fromPresentationXml('./template-folder');
const ppt = await PPTXTemplate.fromPresentationXml({
presentation: './ppt/presentation.xml',
root: './template'
});
// Load flat XML template from server filesystem
try {
const ppt = await PPTXTemplater.fromPresentationXml({
presentation: '/var/www/templates/ppt/presentation.xml',
root: '/var/www/templates'
});
// Modify and save
await ppt.save('/var/www/output/result.pptx');
} catch (err) {
console.error('Failed to load XML presentation:', err);
}
extractPptx
Delegates core actions to slide element sub-managers.
If source PPTX does not exist, throws PPTXError. Overwrites output path only if options.overwrite is true.
Extracts entire zipped PPTX package to filesystem unzipped folder template.
await PPTXTemplater.extractPptx('sample.pptx', './extracted');
await PPTXTemplater.extractPptx('sample.pptx', './extracted', { overwrite: true });
buildPptx
Delegates core actions to slide element sub-managers.
If source folder is missing critical OpenXML parts, throws PPTXError.
Zips and packages OpenXML folder template back into a zipped PPTX archive.
await PPTXTemplater.buildPptx('./extracted', 'output.pptx');
zipManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).zipManager(());
ppt.useSlide(1).zipManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).zipManager(());
} catch (err) {
console.error('API Error: ', err);
}
xmlParser
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).xmlParser(());
ppt.useSlide(1).xmlParser(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).xmlParser(());
} catch (err) {
console.error('API Error: ', err);
}
contentTypesManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).contentTypesManager(());
ppt.useSlide(1).contentTypesManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).contentTypesManager(());
} catch (err) {
console.error('API Error: ', err);
}
relationshipManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).relationshipManager(());
ppt.useSlide(1).relationshipManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).relationshipManager(());
} catch (err) {
console.error('API Error: ', err);
}
slideManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).slideManager(());
ppt.useSlide(1).slideManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).slideManager(());
} catch (err) {
console.error('API Error: ', err);
}
chartManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).chartManager(());
ppt.useSlide(1).chartManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).chartManager(());
} catch (err) {
console.error('API Error: ', err);
}
tableManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).tableManager(());
ppt.useSlide(1).tableManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).tableManager(());
} catch (err) {
console.error('API Error: ', err);
}
shapeManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).shapeManager(());
ppt.useSlide(1).shapeManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).shapeManager(());
} catch (err) {
console.error('API Error: ', err);
}
imageManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).imageManager(());
ppt.useSlide(1).imageManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).imageManager(());
} catch (err) {
console.error('API Error: ', err);
}
textManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).textManager(());
ppt.useSlide(1).textManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).textManager(());
} catch (err) {
console.error('API Error: ', err);
}
hyperlinkManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).hyperlinkManager(());
ppt.useSlide(1).hyperlinkManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).hyperlinkManager(());
} catch (err) {
console.error('API Error: ', err);
}
mediaManager
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).mediaManager(());
ppt.useSlide(1).mediaManager(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).mediaManager(());
} catch (err) {
console.error('API Error: ', err);
}
load
Delegates core actions to slide element sub-managers.
Loads either string filepath or Buffer. Package must be a valid, uncorrupted OpenXML ZIP archive.
Decompresses ZIP archive, indexes content types, preloads all relationship directories, and caches XML nodes.
const ppt = await PPTXTemplater.load('./my_template.pptx');
const buffer = fs.readFileSync('template.pptx');
const ppt = await PPTXTemplater.load(buffer);
async function generateFromS3(s3Buffer) {
try {
const ppt = await PPTXTemplater.load(s3Buffer);
// Perform operations
return await ppt.toBuffer();
} catch (err) {
console.error('Error reading template from S3:', err);
throw err;
}
}
create
Delegates core actions to slide element sub-managers.
No critical edge cases documented. Verify argument boundaries.
Modifies underlying OpenXML nodes to reflect updates on slide serialization.
ppt.useSlide(1).create(());
ppt.useSlide(1).create(()); // Fluent wrapper implementation
try {
ppt.useSlide(1).create(());
} catch (err) {
console.error('API Error: ', err);
}
Packaging & XML Structure
The PowerPoint document model is a zipped Open Packaging Convention (OPC) directory containing structured XML files. Below is the file mapping list for typical slide templates:
PPTX File Layout:
├── [Content_Types].xml (Document Override MIME types)
├── _rels/
│ └── .rels (Root presentation layouts relationship catalog)
├── ppt/
│ ├── presentation.xml (Slide listing, Masters catalog)
│ ├── slides/
│ │ ├── slide1.xml (Elements, shapes, texts runs)
│ │ └── _rels/
│ │ └── slide1.xml.rels (Slide-level resource assets map)
│ ├── media/ (Images assets database: PNG, JPEG, SVG)
│ └── embeddings/ (Excel workbooks backing PowerPoint charts)
XML Security Architecture
To protect your application servers against malicious vectors inside user-supplied templates, the library implements robust, multi-layered XML parsing checks.
🛡️ Attack Protections
- Billion Laughs & XML Bomb Prevention: Automatically rejects XML contain
<!DOCTYPE>or<!ENTITY>tags. - XXE (XML External Entity) Protection: Rejects external system/public links to block local file disclosure vectors.
- Oversized Entity Limits: Imposes hard limits (max 50,000 standard entity instances) to avoid parsing timeouts.
⚙️ Custom Validation API
Exposes validation and recovery utilities directly to your code:
const { validateXml, safeParseXml } = require('node-pptx-templater');
const status = validateXml(userXml);
if (!status.valid) {
console.log('Error details:', status.error);
}
FAQ & Troubleshooting
Q: PowerPoint triggers a "Repair Presentation" alert. How do I fix it?
This happens if relationships are mismatched (pointing to non-existent assets), or if new slide/chart parts are not registered in the override list.
Always use the library's built-in saveToFile() or toBuffer() methods, which automatically execute structural check passes, remap IDs, and sanitize Content Overrides.
Q: Some of my text placeholders inside shapes are not replacing. Why?
PowerPoint editors frequently segment tag characters into separate XML nodes behind the scenes (e.g. {{title}} splits into <a:t>{{ti</a:t><a:t>tle}}</a:t>).
To unify the nodes, highlight the placeholder in PowerPoint, cut it, and paste it back using "Keep Text Only" (this formats it into a single clean XML run).
Q: How does the library resolve "Entity expansion limit exceeded" errors?
We disable internal XML entity expansion in the parser and decode standard character entities (`&`, `<`, etc.) and decimal/hex code points using an optimized, single-level JavaScript decoder. This bypasses limits while blocking XML entity expansion attacks entirely.
Project Roadmap
Upcoming capabilities and core development plans for node-pptx-templater:
💡 Q3 2026: Shapes Rendering
Implement custom shape path creation APIs to construct dynamic rectangles, callouts, and connectors directly in code.
⚡ Q4 2026: Multi-Threading
Support Node worker_threads for slide parsing to execute massive enterprise templates generation in parallel pipelines.
📦 2027: PDF Conversion
Direct headless export of modified PPTX slide decks to PDF without requiring external LibreOffice or PowerPoint processes.
Changelog & Releases
Detailed release notes and updates for node-pptx-templater:
Changelog
All notable changes to this project will be documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.[1.1.0] - 2026-06-12
Added
- Runtime Log Level Control:
PPTXTemplater.load(path, { logLevel: 'debug' })— configure logging at load time without environment variables. Also addedPPTXTemplater.setLogLevel(level)static method andppt.enableDebug()instance shortcut. Supported levels:verbose,debug,info,warn(default),error,silent. The newsetGlobalLogLevel()andresetLogLevel()functions are now exported from the public API. verboseLog Level: New log level belowdebugfor maximum diagnostic output. UsePPTXTemplater.setLogLevel('verbose')to enable.getTableRows(tableId, options): Extract table data as structured JSON. Supports three modes: default (array of objects using header row as keys),{ raw: true }(array of string arrays), and{ includeMetadata: true }(full metadata including row/column count and merged cell info).- Nested
addTableRow()withmergeStrategy: Add rows with nested arrays to create rowspan-merged cells. Options:'rowspan'(OpenXML vertical spans),'auto'(merge identical adjacent values),'none'(expand to flat rows). - 8 new example files in
examples/:image-operations.js,shape-operations.js,z-order.js,slide-import.js,text-search.js,table-extraction.js,nested-table-rows.js,xml-folder-workflow.js. - Documentation Validation Tooling (
scripts/validate-docs.js): Checks that every public method has JSDoc. Exits with code 1 on violations. Run vianpm run docs:validate. - Feature Inventory Generator (
scripts/generate-feature-inventory.js): ParsesPPTXTemplater.jsand outputsdocs/feature-inventory.jsonanddocs/feature-inventory.mdwith all methods grouped by category. Run vianpm run docs:inventory. - Professional logo (
assets/logo.png): Library logo suitable for GitHub, NPM, and documentation. - New npm scripts:
docs:validate,docs:inventory,example:images,example:shapes,example:zorder,example:slide-import,example:text-search,example:table-extraction,example:nested-rows,example:xml-folder.
Fixed
- Horizontal merge preservation: Fixed PowerPoint "repair mode" errors when using
addTableRow()with rows containinggridSpan/hMergeattributes. The cloning logic now correctly preserves horizontal merge attributes and only clears vertical merge state. console.logviolations inChartManager.js(3 calls inupdateChartAsync()),OutputWriter.js(5 calls inprintDebugZip()), andPPTXTemplater.js(8 calls acrossdebugRelationships(),inspectSlide(),inspectXML(),inspectChart(),debugChartRelationships()). All replaced with structuredlogger.debug()/logger.info()calls that respect the configured log level. The library is now completely silent by default — no terminal output at all unless explicitly enabled.
Changed
- Logger system overhauled: Added
verboselevel, runtimesetGlobalLogLevel()function,resetLogLevel()function, and module-levelruntimeLeveloverride. All logger instances now share a mutable runtime level for live updates. - README: Rewritten to be concise, modern, and SEO-friendly. Detailed API docs now live at https://jsuyog2.github.io/node-pptx-templater/.
- Version: Bumped from
1.0.21→1.1.0.
[1.0.6] - 2026-06-02
Added
- XML Validation & Diagnostics Engine: Introduced a suite of tools in
src/utils/xmlUtils.jsfor XML safety and diagnostics:
validateXml(xmlString) — Validates that an XML string is secure and well-formed, checking for DTDs, custom/recursive entities, and XXE.
- safeParseXml(xmlString, file) — Unified wrapper that runs validation and captures detailed diagnostic error logs (file, line, col, error details, and recommendations) on failure.
- scanForEntities(xmlString) — Scans and classifies all XML entity references (standard, custom, numeric, and hex).
- analyzeXmlFile(xmlString) — Computes core file sizing and stats (bytes, lines, elements, attributes, entities).
- reportXmlComplexity(xmlString) — Inspects structural metrics (maximum tag nesting depth, node count, text-to-markup ratio).
- Public API Exports: The new tools are exported from the main library entry point
src/index.js.
Fixed
- XML Entity Expansion Limit Resolution: Permanently resolved the
Entity expansion limit exceededparser crashes on large template files. Deactivated internal entity expansion infast-xml-parserand replaced it with a fast, secure, non-recursive unescaper handling the 5 standard XML/HTML entities and numeric references (decimal and hex code points) natively. - Vulnerability Protections: Integrated strict security checks directly into the validator to block DTD abuse, XML bombs (Billion Laughs), and XXE attacks safely before the parser processes them.
Tests
- Added 13 new unit and integration tests in
tests/unit/XMLSecurity.test.jsvalidating security protections, large-scale entity processing, diagnostics error recovery, and complexity analysis. - Total test count increased from 108 → 121 (all passing).
[1.0.5] - 2026-06-02
Added
- Z-Order (Layer Management) System: Full stacking control for all slide drawing objects — shapes, images, charts, tables, groups, connectors, and SmartArt. Directly manipulates the OpenXML
<p:spTree>element order, matching PowerPoint's native Bring Forward / Send Backward behavior exactly. New APIs:
getObjectOrder(slideIndex) — Returns ordered metadata (id, type, zIndex) for every element on a slide, bottom-to-top.
- bringForward(options) — Moves an object one layer up in the stack.
- sendBackward(options) — Moves an object one layer down.
- bringToFront(options) — Moves an object to the very top of the stack.
- sendToBack(options) — Moves an object to the very bottom of the stack.
- setZIndex(options) — Places an object at an exact 1-based stacking position.
- moveObjectBefore(options) — Positions an object immediately below a named target.
- moveObjectAfter(options) — Positions an object immediately above a named target.
- reorderObjects(options) — Full bulk reorder of the slide stack from a given array.
- applyZOrder(slideIndex, configs) — Applies multiple stacking rules sequentially in one call.
- swapObjects(slideIndex, id1, id2) — Exchanges two objects' positions.
- sortObjects(slideIndex, compareFn) — Sorts the stack using a custom comparator.
- getTopMostObject(slideIndex) / getBottomMostObject(slideIndex) — Inspection helpers.
- normalizeZOrder(slideIndex) — Re-derives and resets internal Z-order state from the current XML.
- Z_ORDER_SYMBOL Export: The
Z_ORDER_SYMBOLis now exported fromsrc/index.jsfor advanced integrations. - ZOrderManager: New dedicated manager class (
src/managers/ZOrderManager.js) encapsulating all layer logic.
Fixed
PPTXTemplater.create()synchronous readiness: AddedpreloadAll()call to#initializeBlank(). Previously, the blank PPTX template's pre-existing slides were registered but their XML was not cached, causing all synchronous operations (including ZOrderManager) to throw"Slide N XML not pre-loaded".
Changed
XMLParserhybrid parsing: Added a secondarypreserveOrder: truefast-xml-parser pass that runs duringparse()whenever a slide<p:spTree>is detected. Extracts DOM element order and attaches it viaZ_ORDER_SYMBOLto each container. Thebuild()method uses a newserializeContainer()recursive function to serialize containers in Z_ORDER_SYMBOL order, injecting the result back into the output XML.ValidationEngine:validate()now audits the shape tree for duplicate shape IDs, reporting them as errors.
Tests
- Added 12 new integration tests in
tests/integration/ZOrder.test.jscovering all Z-order operations. - Total test count increased from 96 → 108 (all passing).
[1.0.3] - 2026-06-02
Added
- Dynamic Formatting in updateTable: Added support for inline cell styling (color fill
fill, text alignmentalign, andfontSize) directly on cell objects passed toupdateTable. - Comprehensive Tailwind Site: Overhauled doc builder script to generate a premium Tailwind CSS documentation portal with clientside search, clipboard copying, sitemap.xml, robots.txt, and Schema.org metadata.
Fixed
- XML Element Ordering: Enforced strict schema-valid element sequence (
a:pPr-> runs ->a:endParaRPr) in slide table cell paragraphs. This resolves the bug where split cells inheriting from template merged cells had their text runs ignored by PowerPoint's XML compiler. - Template Style Inheritance: Fixed a bug in
updateTablewhere cloned rows always copied the first data row (trs[1]). The engine now correctly inherits formatting, alignment, and fill styles from matching indices in the template (trs[i]) when available.
[1.0.2] - 2026-06-02
Added
- Table Cell Merging & Unmerging Engine: Fully implemented horizontal cell spans (
gridSpan,hMerge), vertical cell spans (rowSpan,vMerge), and rectangular block merges. - PowerPoint Repair Protection: Implemented unique 32-bit unsigned
rowIdgeneration inside<a16:rowId>XML tags for all cloned and inserted rows, eliminating PowerPoint's "Repair Mode" error prompts. - Merge Integrations: Integrated template-driven merges (
mergeconfigs array and cell-levelcolSpan/rowSpan) inside the mainupdateTableorchestrator. - Integration Test Suite: Added a comprehensive merge test script under
tests/integration/PPTXMerge.test.js.
[1.0.1] - 2026-05-19
Changed
- CommonJS Target Conversion: Converted the source code modules compilation and packaging layout from pure ES Modules (ESM) to CommonJS (CJS) to ensure compatibility with standard Node.js deployment, packaging, and edge runtime environments.
[1.0.0] - 2026-05-17
Added
PPTXTemplater— main orchestrator class with fluent chainable APIZipManager— PPTX ZIP archive loading, reading, writing, and re-packagingXMLParser— high-performance XML parsing/building viafast-xml-parserRelationshipManager— OpenXML.relsfile parsing and managementSlideManager— slide discovery, ordering, addition, cloning, and removalChartManager— direct chart XML data updates (bar, line, pie, area, scatter)TableManager— table row replacement preserving all formattingHyperlinkManager— external URL and slide-to-slide hyperlink injectionMediaManager— image embedding with SHA-1 deduplicationTemplateEngine—{{placeholder}}replacement with fragmented run normalizationOutputWriter— file, buffer, and stream output- CLI:
build,validate,inspect,extract,debugcommands - Full JSDoc documentation throughout codebase
- Unit tests for all core components (Vitest)
- Integration tests with fixture-based testing
- Performance benchmarks
- GitHub Actions: CI, release, docs workflows
- ESLint + Prettier configuration
- MIT License
Architecture
- Zero PPTX generation library dependencies
- Only uses:
jszip,fast-xml-parser,fs-extra,commander,chalk,ora - Async/await throughout
- Private class fields (
#field) for encapsulation - Modular architecture following SOLID principles