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

TypeDescription
PatchType.PARAGRAPHReplace the placeholder with inline run-level content
PatchType.DOCUMENTReplace 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",
      }),
    ],
  },
}

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

OptionTypeDefaultDescription
outputTypestringOutput format (see Export page)
dataBuffer | Uint8Array | ...Input .docx file data
patchesRecord<string, IPatch>Map of placeholder name to patch content
keepOriginalStylesbooleantruePreserve original run formatting properties
placeholderDelimiters{ start: string, end: string}{ {{, }} }Custom placeholder delimiters
recursivebooleantrueReplace 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 to false to replace only the first.
  • Images and hyperlinks in patch content are automatically added to the document's relationships.
Copyright © 2026