# docx-js API Reference Complete API for creating .docx documents with the `docx` npm package. For advanced features (TOC details, footnotes, PDF conversion), see `docx-js-advanced.md`. ## Setup ```js const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, PageBreak, Header, Footer, PageNumber, NumberFormat, AlignmentType, HeadingLevel, WidthType, BorderStyle, ShadingType, PageOrientation, TabStopType, TabStopPosition, ExternalHyperlink, InternalHyperlink, Bookmark, LevelFormat, TableOfContents, } = require("docx"); const fs = require("fs"); ``` ## Document Creation + Export ```js const doc = new Document({ styles: { /* see Styles section */ }, numbering: { config: [ /* see Lists section */ ] }, sections: [{ properties: { page: { size: { width: 11906, height: 16838 }, margin: { top: 1417, bottom: 1417, left: 1701, right: 1417 }, }, }, headers: { default: new Header({ children: [/* */] }) }, footers: { default: new Footer({ children: [/* */] }) }, children: [ /* Paragraphs, Tables, etc. */ ], }], }); const buffer = await Packer.toBuffer(doc); fs.writeFileSync("output.docx", buffer); ``` ## Paragraph + TextRun ```js new Paragraph({ heading: HeadingLevel.HEADING_1, // or HEADING_2, HEADING_3 alignment: AlignmentType.JUSTIFIED, spacing: { before: 240, after: 120, line: 312 }, // 1.3x mandatory indent: { firstLine: 480 }, // 2-char CJK indent (480 SimSun / 420 YaHei) children: [ new TextRun({ text: "Hello", bold: true, italics: true, size: 24, // 12pt = Xiao Si font: { ascii: "Calibri", eastAsia: "Microsoft YaHei" }, color: "000000", // Pure black for Profile A; for Profile B use palette.body }), ], }); // Additional text formatting options new TextRun({ text: "Underlined", underline: { type: UnderlineType.SINGLE } }) new TextRun({ text: "Highlighted", highlight: "yellow" }) new TextRun({ text: "Strikethrough", strike: true }) new TextRun({ text: "x²", superScript: true }) new TextRun({ text: "H₂O", subScript: true }) new SymbolRun({ char: "2022", font: "Symbol" }) // Bullet • ``` ## Table **⚠️ CRITICAL**: Always set `margins` on TableCell (or at Table level for global default). Without margins, text touches borders. **⚠️ CRITICAL**: Use `ShadingType.CLEAR` — never `ShadingType.SOLID` (causes black cells). **⚠️ CRITICAL — Table Cross-Page Control**: - Header row MUST set `tableHeader: true` (auto-repeat header on page break) - All rows MUST set `cantSplit: true` (prevent row content split across pages) - Title paragraph before table MUST set `keepNext: true` (keep title with table) ```js // ⚠️ Title before table — keepNext keeps title with table new Paragraph({ keepNext: true, // ← critical children: [new TextRun({ text: "Table 1 Feature Comparison", bold: true, size: 21 })], }), new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, borders: { top: { style: BorderStyle.SINGLE, size: 2, color: "9AA6B2" }, bottom: { style: BorderStyle.SINGLE, size: 2, color: "9AA6B2" }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE }, insideHorizontal: { style: BorderStyle.SINGLE, size: 1, color: "D0D0D0" }, insideVertical: { style: BorderStyle.NONE }, }, rows: [ // ⚠️ Header row — tableHeader + cantSplit new TableRow({ tableHeader: true, // auto-repeat on page break cantSplit: true, // prevent row split children: ["Header 1", "Header 2"].map(text => new TableCell({ children: [new Paragraph({ children: [new TextRun({ text, bold: true, size: 21 })] })], shading: { type: ShadingType.CLEAR, fill: "F1F5F9" }, margins: { top: 60, bottom: 60, left: 120, right: 120 }, width: { size: 50, type: WidthType.PERCENTAGE }, }) ), }), // ⚠️ Data rows — cantSplit new TableRow({ cantSplit: true, // prevent row split children: ["Data 1", "Data 2"].map(text => new TableCell({ children: [new Paragraph({ children: [new TextRun({ text, size: 21 })] })], margins: { top: 60, bottom: 60, left: 120, right: 120 }, width: { size: 50, type: WidthType.PERCENTAGE }, }) ), }), ], }); ``` ### Column Widths ```js // Fixed widths (twips) width: { size: 3000, type: WidthType.DXA } // Percentage width: { size: 50, type: WidthType.PERCENTAGE } ``` ## ImageRun **⚠️ CRITICAL**: Always include `type` parameter. Always preserve aspect ratio. ```js const imageBuffer = fs.readFileSync("chart.png"); // Calculate dimensions preserving aspect ratio const displayWidth = 500; const aspectRatio = originalHeight / originalWidth; const displayHeight = Math.round(displayWidth * aspectRatio); new Paragraph({ alignment: AlignmentType.CENTER, children: [ new ImageRun({ data: imageBuffer, transformation: { width: displayWidth, height: displayHeight }, type: "png", // REQUIRED: "png", "jpg", "gif", "bmp" }), ], }); ``` ## PageBreak **⚠️ CRITICAL**: PageBreak MUST be inside a Paragraph. Standalone PageBreak crashes Word. **⚠️ Best Practice**: Attach PageBreak to the end of a **paragraph with text content**. Avoid empty paragraph + PageBreak (may cause blank pages). If using multi-section structure, prefer section breaks over PageBreak. ```js // ✅ Recommended — PageBreak attached to content paragraph new Paragraph({ children: [ new TextRun({ text: "End of section" }), new PageBreak() ] }) // ✅ Acceptable — but prefer section breaks new Paragraph({ children: [new PageBreak()] }) // ✅ Best — use section breaks instead of PageBreak // Place content in different sections — auto page break ``` ## Headers & Footers + Page Numbers ```js headers: { default: new Header({ children: [ new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: "Document Title", size: 18, color: "888888" })], }), ], }), }, footers: { default: new Footer({ children: [ new Paragraph({ alignment: AlignmentType.CENTER, children: [ new TextRun({ children: [PageNumber.CURRENT], size: 18 }), ], }), ], }), }, ``` > ⚠️ **Denominator FORBIDDEN** — never use `PageNumber.TOTAL_PAGES` or "X / Y" format. Show only current page number. ## Styles Definition The example below is for **Chinese documents** (default). For **English documents**, replace `font` with `"Times New Roman"` throughout. ```js styles: { default: { document: { run: { font: { ascii: "Calibri", eastAsia: "Microsoft YaHei" }, size: 24, color: "000000", // Pure black for Profile A; for Profile B use palette.body }, paragraph: { spacing: { line: 312 }, // 1.3x mandatory }, }, heading1: { run: { font: { ascii: "Calibri", eastAsia: "SimHei" }, size: 32, bold: true, color: "0B1220" }, paragraph: { spacing: { before: 360, after: 160, line: 312 } }, }, heading2: { run: { font: { ascii: "Calibri", eastAsia: "SimHei" }, size: 28, bold: true, color: "0B1220" }, paragraph: { spacing: { before: 240, after: 120, line: 312 } }, }, heading3: { run: { font: { ascii: "Calibri", eastAsia: "SimHei" }, size: 24, bold: true, color: "0B1220" }, paragraph: { spacing: { before: 200, after: 100, line: 312 } }, }, }, } ``` ## Lists **⚠️ CRITICAL**: Each separate numbered list MUST use a unique `reference` name. Reusing the same reference causes numbering to continue instead of restarting. ```js // In Document numbering config numbering: { config: [ { reference: "list-features", // unique name! levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } }, }], }, { reference: "list-benefits", // different name for second list! levels: [{ /* same config */ }], }, ], }, // Usage in paragraphs new Paragraph({ numbering: { reference: "list-features", level: 0 }, children: [new TextRun({ text: "First item" })], }) ``` ### Bullet Lists ```js new Paragraph({ bullet: { level: 0 }, children: [new TextRun({ text: "Bullet item" })], }) ``` ## Hyperlinks ### External Link ```js new ExternalHyperlink({ children: [new TextRun({ text: "Click here", style: "Hyperlink" })], link: "https://example.com", }) ``` ### Internal Link (Bookmark) ```js // Define bookmark at target new Paragraph({ children: [ new Bookmark({ id: "section1", children: [new TextRun("Section 1")] }), ], }) // Link to bookmark new InternalHyperlink({ children: [new TextRun({ text: "Go to Section 1", style: "Hyperlink" })], anchor: "section1", }) ``` ## Table of Contents (TOC) **→ See `references/toc.md` for the complete TOC reference.** Quick reminder: (1) Add `TableOfContents` element + PageBreak, (2) Run `python3 "$DOCX_SCRIPTS/add_toc_placeholders.py" output.docx --auto`, (3) Check exit code. ## Tabs ```js new Paragraph({ tabStops: [ { type: TabStopType.RIGHT, position: TabStopPosition.MAX }, ], children: [new TextRun("Left"), new TextRun("\t"), new TextRun("Right")] }) ``` ## Constants Quick Reference - **Underlines:** `SINGLE`, `DOUBLE`, `WAVY`, `DASH` - **Borders:** `SINGLE`, `DOUBLE`, `DASHED`, `DOTTED` - **Numbering:** `DECIMAL` (1,2,3), `UPPER_ROMAN` (I,II,III), `LOWER_LETTER` (a,b,c) - **Symbols:** `"2022"` (•), `"00A9"` (©), `"00AE"` (®), `"2122"` (™)