npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

node-pptx-templater

v1.0.2

Published

Low-level PowerPoint OpenXML template engine for Node.js — generate and edit PPTX files directly through XML manipulation without relying on PowerPoint generation libraries.

Readme

node-pptx-templater

A low-level PowerPoint OpenXML templating engine for Node.js that generates and edits PPTX files directly through XML manipulation without relying on PowerPoint generation libraries.

npm version CI Coverage License: MIT Node.js ES Modules


✨ Features

| Feature | Description | |---|---| | 🏗️ Zero PPTX library dependencies | Direct OpenXML/ZIP manipulation only | | 🔁 Text replacement | Handles fragmented runs ({{placeholders}}) | | 📊 Chart updates | Bar, Line, Pie, Area, Scatter — data only, style preserved | | 📋 Table updates | Replace rows while preserving all formatting | | 🔗 Hyperlinks | External URLs, shape links, slide-to-slide navigation | | ➕ Add new slides | Text, images, shapes with auto-generated XML | | 🎯 Slide selection | By number, ID, or custom tags | | 📤 Multiple outputs | saveToFile(), toBuffer(), toStream() | | 🔍 Validation | Structure validation with error reporting | | 🛠️ CLI | build, validate, inspect, extract, debug | | ⚡ Performance | Lazy loading, media deduplication, async/await |


📦 Installation

npm install node-pptx-templater

Requirements: Node.js ≥ 18.0.0, ES Modules ("type": "module")


🚀 Quick Start

import { PPTXTemplater } from 'node-pptx-templater';

// Load a template PPTX
const ppt = await PPTXTemplater.load('template.pptx');

// Select slide(s) to work on (omit to work on all)
ppt.useSlide(1);

// Replace {{placeholder}} text
ppt.replaceText({
  '{{title}}':    'Quarterly Report',
  '{{year}}':     '2026',
  '{{company}}':  'Acme Corp',
});

// Update chart data
ppt.updateChart('sales-chart', {
  categories: ['Jan', 'Feb', 'Mar'],
  series: [{ name: 'Revenue', values: [120, 150, 180] }],
});

// Update table rows
ppt.updateTable('employees-table', [
  ['Name',  'Role',       'Department'],
  ['Alice', 'Engineer',   'Platform'],
  ['Bob',   'Designer',   'Product'],
]);

// Save output
await ppt.saveToFile('./output/report.pptx');

// Or get a Buffer (for HTTP responses, emails, etc.)
const buffer = await ppt.toBuffer();

📚 API Reference

PPTXTemplater

Static Methods

| Method | Description | |---|---| | PPTXTemplater.load(source) | Load from file path or Buffer | | PPTXTemplater.create() | Create a blank presentation |

Slide Selection

| Method | Description | |---|---| | .useSlide(...refs) | Select slides by number/tag to apply operations | | .useAllSlides() | Reset to all slides | | .tagSlide(num, tag) | Assign custom tag for later selection |

Content Manipulation

| Method | Description | |---|---| | .replaceText(replacements) | Replace {{key}} placeholders | | .updateChart(chartId, data) | Update chart categories/series/values | | .updateTable(tableId, rows) | Replace table row data | | .addHyperlink(options) | Add/replace external hyperlink on text | | .linkSlideNumber(options) | Make slide reference navigate to another slide |

Slide Management

| Method | Description | |---|---| | .addSlide(options) | Add a new slide with elements | | .cloneSlide(num, atPos?) | Duplicate an existing slide | | .removeSlide(num) | Delete a slide | | .reorderSlides(order) | Reorder slides | | .exportSlides(...nums) | Export subset to new engine |

Output

| Method | Description | |---|---| | .saveToFile(path) | Write PPTX to disk | | .toBuffer() | Get PPTX as Node.js Buffer | | .toStream() | Get PPTX as readable stream |

Utilities

| Method | Description | |---|---| | .getInfo() | Presentation metadata | | .validate() | Structure validation | | .slideCount | Total slide count (getter) |


🏗️ Architecture

node-pptx-templater/
├── PPTXTemplater     ← Main orchestrator / public API
│   ├── ZipManager         ← ZIP archive read/write (JSZip)
│   ├── XMLParser          ← XML parse/build (fast-xml-parser)
│   ├── RelationshipManager ← .rels file management
│   ├── SlideManager       ← Slide discovery, ordering, CRUD
│   ├── ChartManager       ← Chart XML data updates
│   ├── TableManager       ← Table row replacement
│   ├── HyperlinkManager   ← Hyperlink injection
│   ├── MediaManager       ← Image embedding + deduplication
│   ├── TemplateEngine     ← {{placeholder}} replacement
│   └── OutputWriter       ← File/Buffer/Stream output

OpenXML PPTX Structure

A .pptx file is a ZIP archive (Open Packaging Convention) containing XML files:

presentation.pptx (ZIP)
├── [Content_Types].xml          # MIME types for all parts
├── _rels/.rels                  # Root relationships
├── ppt/
│   ├── presentation.xml         # Slide list, master references
│   ├── _rels/presentation.xml.rels
│   ├── slides/
│   │   ├── slide1.xml           # Slide content XML
│   │   ├── slide2.xml
│   │   └── _rels/slide1.xml.rels
│   ├── slideLayouts/            # Layout templates
│   ├── slideMasters/            # Master slide designs
│   ├── theme/                   # Color & font themes
│   ├── charts/                  # Embedded chart XML
│   └── media/                   # Images, videos
└── docProps/
    ├── core.xml                 # Title, author, dates
    └── app.xml                  # App metadata

Relationship Flow

presentation.xml
  └─[rId2]──► slides/slide1.xml
                └─[rId1]──► slideLayouts/slideLayout1.xml
                └─[rId2]──► charts/chart1.xml
                              └─ (chart data XML)
                └─[rId3]──► media/image1.png
                └─[rId4]──► https://example.com  (external)

Text Fragmentation Problem & Solution

PowerPoint sometimes splits {{placeholder}} across multiple XML text runs:

<!-- What you write in PowerPoint: -->
{{title}}

<!-- What the XML actually contains: -->
<a:r><a:t>{{ti</a:t></a:r>
<a:r><a:t>tle}}</a:t></a:r>

Our solution: The TemplateEngine normalizes runs within each paragraph by:

  1. Concatenating all run text content
  2. Detecting placeholders in the combined text
  3. Merging affected runs into one (preserving the first run's formatting)
  4. Injecting the replacement value

🖥️ CLI Usage

# Install globally
npm install -g node-pptx-templater

# Build a PPTX from template + JSON data
node-pptx-templater build template.pptx output.pptx --data data.json

# Validate a PPTX structure
node-pptx-templater validate presentation.pptx

# Inspect internal structure
node-pptx-templater inspect presentation.pptx --all

# Extract a slide's XML
node-pptx-templater extract presentation.pptx --slide 1 --out slide1.xml

# Debug a corrupted PPTX
node-pptx-templater debug broken.pptx --fix --out repaired.pptx

Data JSON format for build command

{
  "text": {
    "{{title}}": "Annual Report 2026",
    "{{company}}": "Acme Corp",
    "{{date}}": "January 2026"
  },
  "charts": {
    "sales-chart": {
      "categories": ["Q1", "Q2", "Q3", "Q4"],
      "series": [
        { "name": "Revenue", "values": [145, 210, 190, 250] }
      ]
    }
  },
  "tables": {
    "data-table": [
      ["Name", "Role", "Dept"],
      ["Alice", "Engineer", "Platform"]
    ]
  }
}

📊 Supported Chart Types

| OpenXML Element | Chart Type | |---|---| | c:barChart | Bar / Column | | c:lineChart | Line | | c:pieChart | Pie | | c:areaChart | Area | | c:scatterChart | Scatter / XY | | c:doughnutChart | Doughnut | | c:radarChart | Radar / Spider | | c:bubbleChart | Bubble |


⚡ Performance

| Operation | Benchmark (avg) | |---|---| | Load 50-slide PPTX | ~120ms | | Text replacement (20 placeholders) | ~2ms | | Buffer generation | ~80ms | | Chart update | ~5ms | | Table update | ~3ms |

Run your own: npm run benchmark


🐛 Troubleshooting

Placeholders not being replaced

If {{placeholder}} is not replaced, the text is likely fragmented across runs. Use the PPTX_LOG_LEVEL=debug environment variable to see detailed logs:

PPTX_LOG_LEVEL=debug node your-script.js

Extract the slide XML to inspect:

node-pptx-templater extract template.pptx --slide 1 --out slide1.xml

Look for <a:t> elements and check if the placeholder is split.

Chart not updating

Chart names must match the shape's cNvPr name attribute exactly. Use --inspect --charts to see all chart names:

node-pptx-templater inspect template.pptx --charts

Generated PPTX fails to open

Run the debug command to check for structural issues:

node-pptx-templater debug output.pptx

Common causes:

  • Missing content type entries for new slides
  • Broken relationship IDs
  • Invalid XML characters in replacement values

File is corrupted

node-pptx-templater debug corrupted.pptx --fix --out repaired.pptx

The debug command attempts:

  • Removing invalid XML control characters
  • Fixing unescaped & in text content
  • Repairing broken relationship IDs

🔌 Plugin System

Extend the engine by subclassing PPTXTemplater:

import { PPTXTemplater } from 'pptx-templater';

class MyEngine extends PPTXTemplater {
  /**
   * Custom method: fills a slide from a data object.
   */
  async fillFromData(slideNum, data) {
    this.useSlide(slideNum);

    const textReplacements = {};
    for (const [key, val] of Object.entries(data.text || {})) {
      textReplacements[`{{${key}}}`] = String(val);
    }

    this.replaceText(textReplacements);

    if (data.chart) {
      this.updateChart(data.chart.id, data.chart);
    }

    return this;
  }
}

// Usage
const ppt = await MyEngine.load('template.pptx');
await ppt.fillFromData(1, {
  text: { title: 'My Report', date: '2026-01-01' },
  chart: { id: 'sales', categories: ['Q1'], series: [{ name: 'Rev', values: [100] }] },
});
await ppt.saveToFile('output.pptx');

🛣️ Roadmap

  • [ ] SmartArt data update
  • [ ] Speaker notes modification
  • [ ] Slide transitions and animation metadata editing
  • [ ] PPTX → HTML export (read-only)
  • [ ] Password-protected PPTX support
  • [ ] Native chart creation from scratch (without template)
  • [ ] Watch mode for development
  • [ ] Browser/WASM support (via jszip already)

🤝 Contributing

See CONTRIBUTING.md for guidelines.

Quick steps:

git clone https://github.com/jsuyog2/node-pptx-templater.git
cd node-pptx-templater
npm install
npm test

📄 License

MIT — see LICENSE