docx-html-replacer
v1.1.0
Published
Open-source rich-text (HTML) placeholder replacement for DOCX templates. Automatically detects HTML vs plain text and converts to native Word formatting.
Downloads
98
Maintainers
Readme
docx-html-replacer
Open-source rich-text (HTML) placeholder replacement for DOCX templates.
Replace <<placeholder>> tags in .docx files with plain text or HTML content that gets automatically converted to native Word formatting (bold, italic, headings, lists, links, and more).
Quick Start
npm install docx-html-replacerimport { replaceInDocx } from 'docx-html-replacer';
import * as fs from 'fs';
const template = fs.readFileSync('template.docx');
const result = await replaceInDocx(template, {
title: 'Quarterly Report',
date: '2025-11-04',
content: '<h1>Summary</h1><ul><li>Revenue up 15%</li><li>Costs down 8%</li></ul>',
});
fs.writeFileSync('output.docx', result);Your template uses <<placeholder>> syntax — just create a .docx file with tags like <<title>>, <<date>>, <<content>> and the library handles the rest.
Features
- Automatic HTML detection — values containing HTML tags are converted to native Word (OOXML) formatting; plain text is inserted as-is.
- Rich formatting support — bold, italic, underline, strikethrough, headings (
<h1>–<h6>), ordered/unordered lists, hyperlinks, tables. - Malformed placeholder safety — gracefully handles
<<<...>>>,<<<<...>>>>, and mismatched brackets without crashing. - Font customization — configurable font family and size (default: Aptos 10pt).
- Paragraph justification — optional justified alignment for all paragraphs (list items stay left-aligned).
- Strict mode — optionally throw errors when placeholders have no replacement value.
- Case-insensitive matching —
<<Name>>and<<name>>both match the same replacement key. - Custom logger — plug in your own logging (Winston, Pino, console, etc.) via the
DocxLoggerinterface. - Structured error handling — all errors throw
DocxReplacerErrorwith a machine-readablecode, human-readablemessage, and optionaldetails. - Input validation — template size limits, replacement value checks, and prototype-pollution protection out of the box.
- Cross-runtime input — accepts
Buffer,Uint8Array, orArrayBufferas template input.
API
replaceInDocx(template, replacements, options?)
Replace placeholders in a DOCX template buffer.
| Parameter | Type | Description |
| -------------- | ----------------------------- | --------------------------------------------------- |
| template | DocxInput | The .docx file as a Buffer, Uint8Array, or ArrayBuffer |
| replacements | Record<string, string> | Key-value map of placeholder names to values |
| options | ReplaceOptions (optional) | Configuration for font, justification, logger, etc. |
Returns: Promise<Buffer> — the generated .docx file.
Options
interface ReplaceOptions {
font?: FontOptions | false; // Font config, or false to skip font styling
justify?: boolean; // Justify paragraphs (default: true)
logger?: DocxLogger; // Optional logger
strict?: boolean; // Throw on unreplaced placeholders (default: false)
}
interface FontOptions {
fontFamily?: string; // Default: 'Aptos'
fontSize?: number; // In half-points. Default: 20 (10pt)
}applyFontStylingOnly(template, options?)
Apply font styling to a DOCX buffer without performing any placeholder replacement.
| Parameter | Type | Description |
| ---------- | --------------------------------- | -------------------------------------------------------- |
| template | DocxInput | The .docx file as a Buffer, Uint8Array, or ArrayBuffer |
| options | FontStylingOptions (optional) | Font, justification, logger |
Returns: Promise<Buffer>
isHtmlString(str)
Utility function: returns true if the given string contains HTML tags (tags must start with a letter or /). Plain text with angle brackets (e.g. 5 < 10 > 5) returns false.
Error Handling
All errors thrown by the library are instances of DocxReplacerError, which extends Error with:
code— a machine-readableDocxErrorCodestring for programmatic handlingdetails— an optional object with extra context (e.g. which key failed)cause— the original error, when wrapping a third-party failure
Error Codes
| Code | When it's thrown |
| ------------------------ | ------------------------------------------------------------- |
| INVALID_TEMPLATE | Template is not a Buffer/Uint8Array/ArrayBuffer, or is empty |
| TEMPLATE_TOO_LARGE | Template exceeds the 100 MB size limit |
| CORRUPT_TEMPLATE | File is not a valid ZIP/DOCX or is missing word/document.xml|
| INVALID_REPLACEMENT | A replacement key is reserved, value is not a string, or value exceeds 10 MB |
| PLACEHOLDER_MISSING | Strict mode: a placeholder in the template has no replacement |
| HTML_CONVERSION_FAILED | The HTML content for a placeholder could not be converted |
| RENDER_FAILED | The template could not be rendered (e.g. malformed syntax) |
Example
import { replaceInDocx, DocxReplacerError } from 'docx-html-replacer';
try {
const result = await replaceInDocx(template, replacements);
} catch (err) {
if (err instanceof DocxReplacerError) {
console.error(`[${err.code}] ${err.message}`);
// err.details — extra context (key, size, etc.)
// err.cause — original error, if any
}
}Examples
Plain text replacement
const result = await replaceInDocx(template, {
company_name: 'Acme Corp',
date: '2025-11-04',
ref_number: 'REF-12345',
});Rich HTML replacement
const result = await replaceInDocx(template, {
summary: `
<h2>Project Status</h2>
<p>The project is <b>on track</b> for delivery.</p>
<ul>
<li>Phase 1: <i>Complete</i></li>
<li>Phase 2: In Progress</li>
<li>Phase 3: Planned</li>
</ul>
<p>See <a href="https://example.com/dashboard">dashboard</a> for details.</p>
`,
});Custom font and no justification
const result = await replaceInDocx(
template,
{ title: 'My Report' },
{
font: { fontFamily: 'Calibri', fontSize: 24 }, // 12pt
justify: false,
}
);Strict mode
import { replaceInDocx, DocxReplacerError } from 'docx-html-replacer';
try {
const result = await replaceInDocx(
template,
{ title: 'Only Title' },
{ strict: true }
);
} catch (err) {
if (err instanceof DocxReplacerError && err.code === 'PLACEHOLDER_MISSING') {
console.error(err.message);
// 'The placeholder "<<date>>" in your template has no replacement value. ...'
}
}Exports
// Functions
export { replaceInDocx, applyFontStylingOnly, isHtmlString };
// Error class
export { DocxReplacerError };
// Types
export type {
DocxInput,
DocxErrorCode,
ReplaceOptions,
FontStylingOptions,
FontOptions,
DocxLogger,
};Supported HTML Tags
| Tag | Description |
| ------------------------ | ------------------------ |
| <p> | Paragraphs |
| <h1> – <h6> | Headings |
| <b>, <strong> | Bold |
| <i>, <em> | Italic |
| <u>, <ins> | Underline |
| <s>, <del> | Strikethrough |
| <ul>, <ol>, <li> | Lists |
| <a href="..."> | Hyperlinks |
| <table>, <tr>, <td>| Tables |
| <br> | Line breaks |
| <span> | Inline styling |
| <sub>, <sup> | Subscript / Superscript |
| <code> | Code (gray highlight) |
| <blockquote> | Block quotes |
Known Limitations
- DOCX only — does not support PPTX or XLSX.
- Body content only — placeholders in headers, footers, and other document parts are not processed (only
word/document.xml). - HTML-to-OOXML conversion relies on html-to-docx; some advanced CSS may not convert perfectly.
- Complex nested tables may have layout differences between browsers and Word.
- Image support (
<img>) is not included in this version.
Third-Party Licenses
This package depends on the following MIT-licensed open-source libraries:
- docxtemplater — DOCX template engine
- pizzip — ZIP file handling
- html-to-docx — HTML to DOCX conversion
- xml-js — XML/JSON conversion
Disclaimer: This package is independent and not affiliated with Docxtemplater or its commercial modules.
