
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
docxmlater
Advanced tools
A comprehensive DOCX editing framework for creating, reading, and manipulating Microsoft Word documents
A comprehensive, production-ready TypeScript/JavaScript framework for creating, reading, and manipulating Microsoft Word (.docx) documents programmatically.
validateBookmarkPairs())getFirstParagraph(), getLastParagraph())hMerge) supportfixed/auto)w:default="1")npm install docxmlater
import { Document } from 'docxmlater';
// Create a new document
const doc = Document.create();
// Add a paragraph
const para = doc.createParagraph();
para.addText('Hello, World!', { bold: true, fontSize: 24 });
// Save to file
await doc.save('hello.docx');
// Don't forget to dispose
doc.dispose();
import { Document } from 'docxmlater';
// Load existing document
const doc = await Document.load('input.docx');
// Find and replace text
doc.replaceText(/old text/g, 'new text');
// Add a new paragraph
const para = doc.createParagraph();
para.addText('Added paragraph', { italic: true });
// Save modifications
await doc.save('output.docx');
doc.dispose();
import { Document } from 'docxmlater';
const doc = Document.create();
// Create a 3x4 table
const table = doc.createTable(3, 4);
// Set header row
const headerRow = table.getRow(0);
headerRow.getCell(0).addParagraph().addText('Column 1', { bold: true });
headerRow.getCell(1).addParagraph().addText('Column 2', { bold: true });
headerRow.getCell(2).addParagraph().addText('Column 3', { bold: true });
headerRow.getCell(3).addParagraph().addText('Column 4', { bold: true });
// Add data
table.getRow(1).getCell(0).addParagraph().addText('Data 1');
table.getRow(1).getCell(1).addParagraph().addText('Data 2');
// Apply borders
table.setBorders({
top: { style: 'single', size: 4, color: '000000' },
bottom: { style: 'single', size: 4, color: '000000' },
left: { style: 'single', size: 4, color: '000000' },
right: { style: 'single', size: 4, color: '000000' },
insideH: { style: 'single', size: 4, color: '000000' },
insideV: { style: 'single', size: 4, color: '000000' },
});
await doc.save('table.docx');
doc.dispose();
import { Document } from 'docxmlater';
import { readFileSync } from 'fs';
const doc = Document.create();
// Load image from file
const imageBuffer = readFileSync('photo.jpg');
// Add image to document
const para = doc.createParagraph();
await para.addImage(imageBuffer, {
width: 400,
height: 300,
format: 'jpg',
});
await doc.save('with-image.docx');
doc.dispose();
import { Document } from 'docxmlater';
const doc = await Document.load('document.docx');
// Get all hyperlinks
const hyperlinks = doc.getHyperlinks();
console.log(`Found ${hyperlinks.length} hyperlinks`);
// Update URLs in batch (30-50% faster than manual iteration)
doc.updateHyperlinkUrls('http://old-domain.com', 'https://new-domain.com');
// Fix fragmented hyperlinks from Google Docs
const mergedCount = doc.defragmentHyperlinks({
resetFormatting: true, // Fix corrupted fonts
});
console.log(`Merged ${mergedCount} fragmented hyperlinks`);
await doc.save('updated.docx');
doc.dispose();
import { Document, Style } from 'docxmlater';
const doc = Document.create();
// Create custom paragraph style
const customStyle = new Style('CustomHeading', 'paragraph');
customStyle.setName('Custom Heading');
customStyle.setRunFormatting({
bold: true,
fontSize: 32,
color: '0070C0',
});
customStyle.setParagraphFormatting({
alignment: 'center',
spacingAfter: 240,
});
// Add style to document
doc.getStylesManager().addStyle(customStyle);
// Apply style to paragraph
const para = doc.createParagraph();
para.addText('Styled Heading');
para.applyStyle('CustomHeading');
await doc.save('styled.docx');
doc.dispose();
import { Document, CompatibilityMode } from 'docxmlater';
const doc = await Document.load('legacy.docx');
// Check compatibility mode
console.log(`Mode: ${doc.getCompatibilityMode()}`); // e.g., 12 (Word 2007)
if (doc.isCompatibilityMode()) {
// Get detailed compatibility info
const info = doc.getCompatibilityInfo();
console.log(`Legacy flags: ${info.legacyFlags.length}`);
// Upgrade to Word 2013+ mode (equivalent to File > Info > Convert)
const report = doc.upgradeToModernFormat();
console.log(`Removed ${report.removedFlags.length} legacy flags`);
console.log(`Added ${report.addedSettings.length} modern settings`);
}
await doc.save('modern.docx');
doc.dispose();
Creation & Loading:
Document.create(options?) - Create new documentDocument.load(filepath, options?) - Load from fileDocument.loadFromBuffer(buffer, options?) - Load from memoryHandling Tracked Changes:
By default, docXMLater accepts all tracked changes during document loading to prevent corruption:
// Default: Accepts all changes (recommended)
const doc = await Document.load('document.docx');
// Explicit control
const doc = await Document.load('document.docx', {
revisionHandling: 'accept' // Accept all changes (default)
// OR
revisionHandling: 'strip' // Remove all revision markup
// OR
revisionHandling: 'preserve' // Keep tracked changes (may cause corruption, but should not do so - report errors if found)
});
Revision Handling Options:
'accept' (default): Removes revision markup, keeps inserted content, removes deleted content'strip': Removes all revision markup completely'preserve': Keeps tracked changes as-is (may cause Word "unreadable content" errors)Why Accept By Default?
Documents with tracked changes can cause Word corruption errors during round-trip processing due to revision ID conflicts. Accepting changes automatically prevents this issue while preserving document content.
Content Management:
createParagraph() - Add paragraphcreateTable(rows, cols) - Add tablecreateSection() - Add sectiongetBodyElements() - Get all body contentSearch & Replace:
findText(pattern) - Find text matchesreplaceText(pattern, replacement) - Replace textfindParagraphsByText(pattern) - Find paragraphs containing text/regexgetParagraphsByStyle(styleId) - Get paragraphs with specific stylegetRunsByFont(fontName) - Get runs using a specific fontgetRunsByColor(color) - Get runs with a specific colorBulk Formatting:
setAllRunsFont(fontName) - Apply font to all textsetAllRunsSize(size) - Apply font size to all textsetAllRunsColor(color) - Apply color to all textgetFormattingReport() - Get document formatting statisticsHyperlinks:
getHyperlinks() - Get all hyperlinksupdateHyperlinkUrls(oldUrl, newUrl) - Batch URL updatedefragmentHyperlinks(options?) - Fix fragmented linkscollectAllReferencedHyperlinkIds() - Comprehensive scan of all hyperlink relationship IDs (includes nested tables, headers/footers, footnotes/endnotes)Statistics:
getWordCount() - Count wordsgetCharacterCount(includeSpaces?) - Count charactersestimateSize() - Estimate file sizeCompatibility Mode:
getCompatibilityMode() - Get document's Word version mode (11/12/14/15)isCompatibilityMode() - Check if document targets a legacy Word versiongetCompatibilityInfo() - Get full parsed compat settingsupgradeToModernFormat() - Upgrade to Word 2013+ mode (removes legacy flags)Footnotes & Endnotes:
createFootnote(paragraph, text) - Add footnotecreateEndnote(paragraph, text) - Add endnoteclearFootnotes() / clearEndnotes() - Remove all notesgetFootnoteManager() / getEndnoteManager() - Access note managersNumbering:
restartNumbering(numId, level?, startValue?) - Restart list numbering (creates new instance with startOverride)cleanupUnusedNumbering() - Remove unused numbering definitions (scans body, headers, footers, footnotes, endnotes)consolidateNumbering(options?) - Merge duplicate abstract numbering definitionsvalidateNumberingReferences() - Fix orphaned numId referencesShading:
getComputedCellShading(table, row, col) - Resolve effective cell shading with inheritanceDocument Sanitization:
flattenFieldCodes() - Strip INCLUDEPICTURE field markup, preserving embedded imagesstripOrphanRSIDs() - Remove orphan RSIDs from settings.xmlclearDirectSpacingForStyles(styleIds) - Remove direct spacing overrides from styled paragraphsImage Optimization:
optimizeImages() - Lossless PNG re-compression and BMP-to-PNG conversion (zero dependencies)Saving:
save(filepath) - Save to filetoBuffer() - Save to Bufferdispose() - Free resources (important!)Content:
addText(text, formatting?) - Add text runaddRun(run) - Add custom runaddHyperlink(hyperlink) - Add hyperlinkaddImage(buffer, options) - Add imageFormatting:
setAlignment(alignment) - Left, center, right, justifysetIndentation(options) - First line, hanging, left, rightsetSpacing(options) - Line spacing, before/aftersetBorders(borders) - Paragraph borderssetShading(shading) - Background colorapplyStyle(styleId) - Apply paragraph styleProperties:
setKeepNext(value) - Keep with next paragraphsetKeepLines(value) - Keep lines togethersetPageBreakBefore(value) - Page break beforeclearSpacing() - Remove direct spacing (inherit from style)Numbering:
setNumbering(numId, level) - Apply list numberingText:
setText(text) - Set run textgetText() - Get run textCharacter Formatting:
setBold(value) - Bold textsetItalic(value) - Italic textsetUnderline(style?) - UnderlinesetStrikethrough(value) - StrikethroughsetFont(name) - Font familysetFontSize(size) - Font size in pointssetColor(color) - Text color (hex)setHighlight(color) - Highlight colorAdvanced:
setSubscript(value) - SubscriptsetSuperscript(value) - SuperscriptsetSmallCaps(value) - Small capitalssetAllCaps(value) - All capitalsclearMatchingFormatting(styleFormatting) - Remove formatting matching a style (for inheritance)getPropertyChangeRevision() - Get run property change revision (w:rPrChange)setPropertyChangeRevision(propChange) - Set run property change revisionStructure:
addRow() - Add rowgetRow(index) - Get row by indexgetCell(row, col) - Get specific cellFormatting:
setBorders(borders) - Table borderssetAlignment(alignment) - Table alignmentsetWidth(width) - Table widthsetLayout(layout) - Fixed or auto layoutStyle:
applyStyle(styleId) - Apply table styleContent:
addParagraph() - Add paragraph to cellgetParagraphs() - Get all paragraphsFormatting:
setBorders(borders) - Cell borderssetShading(color) - Cell backgroundsetVerticalAlignment(alignment) - Top, center, bottomsetWidth(width) - Cell widthSpanning:
setHorizontalMerge(mergeType) - Horizontal mergesetVerticalMerge(mergeType) - Vertical mergeConvenience Methods:
setTextAlignment(alignment) - Set alignment for all paragraphssetAllParagraphsStyle(styleId) - Apply style to all paragraphssetAllRunsFont(fontName) - Apply font to all runssetAllRunsSize(size) - Apply font size to all runssetAllRunsColor(color) - Apply color to all runsContent Management:
removeTrailingBlankParagraphs(options?) - Remove trailing blank paragraphs from cellremoveParagraph(index) - Remove paragraph at index (updates nested content positions)addParagraphAt(index, paragraph) - Insert paragraph at index (updates nested content positions)Table Style Shading:
updateTableStyleShading(oldColor, newColor) - Update shading colors in styles.xmlupdateTableStyleShadingBulk(settings) - Bulk update table style shadingremoveTrailingBlanksInTableCells(options?) - Remove trailing blanks from all table cellsSorting:
sortRows(columnIndex, options?) - Sort table rows by columnLine Numbering:
setLineNumbering(options) - Enable line numberinggetLineNumbering() - Get line numbering settingsclearLineNumbering() - Disable line numberingResolution:
resolve() - Mark comment as resolvedunresolve() - Mark comment as unresolvedisResolved() - Check if comment is resolvedFiltering:
getResolvedComments() - Get all resolved commentsgetUnresolvedComments() - Get all unresolved commentsUnit Conversions:
import { twipsToPoints, inchesToTwips, emusToPixels } from 'docxmlater';
const points = twipsToPoints(240); // 240 twips = 12 points
const twips = inchesToTwips(1); // 1 inch = 1440 twips
const pixels = emusToPixels(914400, 96); // 914400 EMUs = 96 pixels at 96 DPI
Validation:
import { validateRunText, detectXmlInText, cleanXmlFromText } from 'docxmlater';
// Detect XML patterns in text
const result = validateRunText('Some <w:t>text</w:t>');
if (result.hasXml) {
console.warn(result.message);
const cleaned = cleanXmlFromText(result.text);
}
Corruption Detection:
import { detectCorruptionInDocument } from 'docxmlater';
const doc = await Document.load('suspect.docx');
const report = detectCorruptionInDocument(doc);
if (report.isCorrupted) {
console.log(`Found ${report.locations.length} corruption issues`);
report.locations.forEach((loc) => {
console.log(`Line ${loc.lineNumber}: ${loc.issue}`);
console.log(`Suggested fix: ${loc.suggestedFix}`);
});
}
Full TypeScript definitions included:
import {
Document,
Paragraph,
Run,
Table,
RunFormatting,
ParagraphFormatting,
DocumentProperties,
} from 'docxmlater';
// Type-safe formatting
const formatting: RunFormatting = {
bold: true,
fontSize: 12,
color: 'FF0000',
};
// Type-safe document properties
const properties: DocumentProperties = {
title: 'My Document',
author: 'John Doe',
created: new Date(),
};
Current Version: 10.1.7
See CHANGELOG.md for detailed version history.
The framework includes comprehensive test coverage:
Run tests:
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
dispose() to free resources after document operationsThe framework follows a modular architecture:
src/
├── core/ # Document, Parser, Generator, Validator
├── elements/ # Paragraph, Run, Table, Image, etc.
├── formatting/ # Style, Numbering managers
├── managers/ # Drawing, Image, Relationship managers
├── constants/ # Compatibility mode constants, limits
├── types/ # Type definitions (compatibility, formatting, lists)
├── tracking/ # Change tracking context
├── validation/ # Revision validation rules
├── helpers/ # Cleanup utilities
├── xml/ # XML generation and parsing
├── zip/ # ZIP archive handling
└── utils/ # Validation, units, error handling
Key design principles:
docXMLater includes multiple security measures to protect against common attack vectors:
The XML parser uses position-based parsing instead of regular expressions, preventing catastrophic backtracking attacks that can cause denial of service.
Size Limits:
// Configure size limits
const doc = await Document.load('large.docx', {
sizeLimits: {
warningSizeMB: 100,
maxSizeMB: 500,
},
});
Nesting Depth:
import { XMLParser } from 'docxmlater';
// Parse with custom depth limit
const obj = XMLParser.parseToObject(xml, {
maxNestingDepth: 512, // Increase if needed
});
File paths within DOCX archives are validated to prevent directory traversal attacks:
../ path sequencesAll text content is properly escaped using:
XMLBuilder.escapeXmlText() for element contentXMLBuilder.escapeXmlAttribute() for attribute valuesThis prevents injection of malicious XML elements through user-provided text content.
All text files are explicitly UTF-8 encoded per ECMA-376 specification, preventing encoding-related vulnerabilities.
jszip - ZIP archive handlingMIT
Contributions welcome! Please:
Built with careful attention to the ECMA-376 Office Open XML specification. Special thanks to the OpenXML community for comprehensive documentation and examples.
FAQs
A comprehensive DOCX editing framework for creating, reading, and manipulating Microsoft Word documents
The npm package docxmlater receives a total of 54 weekly downloads. As such, docxmlater popularity was classified as not popular.
We found that docxmlater demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.