Patching
Patch an existing .pptx template in three ways: replace {{placeholder}} tokens, find-and-replace literal text, or override document metadata.
patchPresentation
Replaces placeholders in an existing .pptx file:
import { patchPresentation, generatePresentation } from "@office-open/pptx";
import { writeFileSync } from "node:fs";
// Create a template with placeholders
const templateBuffer = await generatePresentation({
title: "Patch Demo",
slides: [
{
children: [
{
shape: {
x: "2.1cm",
y: "3.2cm",
width: "19.1cm",
height: "2.1cm",
textBody: {
children: [{ children: [{ text: "Hello {{name}}!" }] }],
},
},
},
],
},
],
});
// Patch the template
const result = await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
placeholders: {
name: [{ text: "World", bold: true, size: 24 }],
},
});
writeFileSync("output.pptx", result);
Placeholders
Placeholder keys are wrapped in delimiters (default {{ and }}) and matched against the slide text. Each value is inline run-level content, reusing the same RunOptions vocabulary as generatePresentation: a single run, an array of runs, or a plain string shorthand.
The original run's formatting properties (font, size, color, bold, etc.) are preserved by default. Any property you set (color, fill, font, hyperlinks, …) is serialized via the same descriptor as generatePresentation.
placeholders: {
title: [
{ text: "Hello ", bold: true },
{ text: "World", fill: { type: "solid", color: "FF0000" } },
],
link: { text: "Click", hyperlink: { url: "https://example.com" } },
plain: "just text",
}
Find and Replace
Replace literal text without any delimiters — the keys are matched verbatim. Useful for rebranding or updating fixed wording in a template:
const result = await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
findReplace: {
"Acme Corp": [{ text: "Globex", bold: true }],
Draft: "Final",
},
});
Core Properties
Override document metadata (docProps/core.xml). Values are merged over the existing core properties — supply only the fields you want to change:
const result = await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
coreProperties: { title: "Quarterly Review", creator: "Jane Doe" },
});
Slides
Append new slides or replace existing ones by index (0-based, in sldIdLst order). Each entry reuses the full SlideOptions vocabulary from generatePresentation:
const result = await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
slides: {
append: [
{
children: [
{
shape: {
x: "0.0cm",
y: "0.0cm",
width: "15.9cm",
height: "10.6cm",
textBody: { text: "New slide" },
},
},
],
},
],
replace: {
0: {
children: [
{
shape: {
x: "0.0cm",
y: "0.0cm",
width: "15.9cm",
height: "10.6cm",
textBody: { text: "Replaced" },
},
},
],
},
},
},
});
Appended slides are serialized through the same slide stringifier as generation and wired into sldIdLst, the presentation relationships, and [Content_Types].xml. Each appended slide inherits the template's first slide layout — it cannot reference layouts, masters, or media that the template does not already contain. Replaced slides keep their existing identity (sldId, rId, and relationships).
Comments
Append comments to existing slides, keyed by 0-based slide index (in sldIdLst order). Each comment reuses the SlideCommentOptions vocabulary from generatePresentation (see ). Authors are merged into commentAuthors.xml (deduped by name, ids continued) and per-slide comments are merged into ppt/comments/commentN.xml:
const result = await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
comments: {
0: [{ author: "Alice", text: "Review the opening", x: "2.6cm", y: "4.0cm" }],
1: [{ author: "Bob", text: "Add a chart here", x: "2.6cm", y: "4.0cm" }],
},
});
Existing authors and comments are preserved — new entries are appended and re-serialized.
Custom Delimiters
Default delimiters are {{ and }}. Change them with placeholderDelimiters:
await patchPresentation({
outputType: "nodebuffer",
data: templateBuffer,
placeholders: { name: [{ text: "John" }] },
placeholderDelimiters: { start: "<<", end: ">>" },
});
Options
| Option | Type | Default | Description |
|---|---|---|---|
outputType | string | — | Output format (see Export page) |
data | Buffer | Uint8Array | ... | — | Input .pptx file data |
placeholders | Record<string, RunOptions | RunOptions[] | string> | — | Delimiter-wrapped placeholder name → run content |
findReplace | Record<string, RunOptions | RunOptions[] | string> | — | Literal find string → run content (no delimiters) |
coreProperties | Partial<CorePropertiesOptions> | — | Core metadata override, merged over existing values |
slides | { append?, replace? } | — | Append slides or replace slides by 0-based index |
comments | Record<number, SlideCommentOptions[]> | — | Append comments to slides by 0-based index (merged with existing) |
keepOriginalStyles | boolean | true | Preserve original run formatting properties |
placeholderDelimiters | { start: string, end: string} | { start: "{{", end: "}}" } | Custom placeholder delimiters |
Tips
- Placeholders span across split runs in PowerPoint — the library handles this automatically.
placeholdersandfindReplaceshare one engine; combine both in a single call.- Scanning covers slides, slide masters, slide layouts, and notes slides — replacing text in a master/layout propagates to every dependent slide.
- Hyperlinks introduced by patch runs are registered into each slide's relationship part automatically.