DOCX
Patching
Modify existing .docx files by replacing placeholders with new content
Patch an existing .docx template by replacing {{placeholder}} tokens with new content — paragraphs, tables, images, hyperlinks, and more.
patchDocument
Replaces placeholders in an existing .docx file:
import {
patchDocument,
PatchType,
TextRun,
Paragraph,
Table,
TableRow,
TableCell,
} from "@office-open/docx";
import { readFileSync, writeFileSync } from "node:fs";
const result = await patchDocument({
outputType: "nodebuffer",
data: readFileSync("template.docx"),
patches: {
name: {
type: PatchType.PARAGRAPH,
children: [new TextRun("John Doe")],
},
},
});
writeFileSync("output.docx", result);
PatchType
| Type | Description |
|---|---|
PatchType.PARAGRAPH | Replace the placeholder with inline run-level content |
PatchType.DOCUMENT | Replace the placeholder with block-level content |
PARAGRAPH
Replaces the placeholder text inside a paragraph with new runs. The original run's formatting properties (font, size, color, bold, etc.) are preserved by default.
patches: {
title: {
type: PatchType.PARAGRAPH,
children: [
new TextRun({ text: "Hello ", bold: true }),
new TextRun("World"),
],
},
}
DOCUMENT
Replaces the placeholder with block-level elements (paragraphs, tables, etc.). The surrounding context is preserved.
patches: {
content: {
type: PatchType.DOCUMENT,
children: [
new Paragraph("First paragraph"),
new Paragraph("Second paragraph"),
new Table({
rows: [
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Cell")] }),
],
}),
],
}),
],
},
}
Images
Replace a placeholder with an image:
patches: {
logo: {
type: PatchType.PARAGRAPH,
children: [
new ImageRun({
data: readFileSync("logo.png"),
transformation: { width: 200, height: 100 },
type: "png",
}),
],
},
}
Hyperlinks
Include hyperlinks in patch content:
patches: {
website: {
type: PatchType.PARAGRAPH,
children: [
new TextRun("Visit "),
new ExternalHyperlink({
children: [new TextRun("our website")],
link: "https://example.com",
}),
],
},
}
Custom Delimiters
Default delimiters are {{ and }}. Change them with placeholderDelimiters:
await patchDocument({
outputType: "nodebuffer",
data: templateBuffer,
patches: { name: { type: PatchType.PARAGRAPH, children: [new TextRun("John")] } },
placeholderDelimiters: { start: "<<", end: ">>" },
});
Options
| Option | Type | Default | Description |
|---|---|---|---|
outputType | string | — | Output format (see Export page) |
data | Buffer | Uint8Array | ... | — | Input .docx file data |
patches | Record<string, IPatch> | — | Map of placeholder name to patch content |
keepOriginalStyles | boolean | true | Preserve original run formatting properties |
placeholderDelimiters | { start: string, end: string} | { {{, }} } | Custom placeholder delimiters |
recursive | boolean | true | Replace all occurrences (not just the first) |
patchDetector
Scan a template to discover all placeholder keys before patching:
import { patchDetector } from "@office-open/docx";
const placeholders = await patchDetector({
data: readFileSync("template.docx"),
});
// ["name", "title", "content", ...]
Tips
- Placeholders span across split runs in Word — the library handles this automatically.
- Use
keepOriginalStyles: true(default) to inherit the template's run formatting (font, size, color, etc.) when replacing text. recursive: true(default) replaces all occurrences of each placeholder; set tofalseto replace only the first.- Images and hyperlinks in patch content are automatically added to the document's relationships.