Skip to main content

docx

Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). For CREATING new documents (report, memo, letter, résumé, contract from scratch), call the built-in tool `renderDocx` instead — it renders Markdown to .docx in milliseconds without forking Node.js. This skill remains authoritative for EDITING existing .docx (unpack/edit XML/pack), tracked changes, comments, image manipulation, find-and-replace, and conversions. Triggers include: "Word doc", "word document", ".docx", or requests to edit/extract/restructure existing Word files. Do NOT use for PDFs, spreadsheets, or general coding tasks unrelated to document generation.

Source facts

Repository
mateaix/mateclaw
Last source activity
July 11, 2026 at 04:15
Detected SKILL.md language
English
Stars
1,154
Forks
342

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
61 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
docx
version
1.1.0
description
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). For CREATING new documents (report, memo, letter, résumé, contract from scratch), call the built-in tool `renderDocx` instead — it renders Markdown to .docx in milliseconds without forking Node.js. This skill remains authoritative for EDITING existing .docx (unpack/edit XML/pack), tracked changes, comments, image manipulation, find-and-replace, and conversions. Triggers include: "Word doc", "word document", ".docx", or requests to edit/extract/restructure existing Word files. Do NOT use for PDFs, spreadsheets, or general coding tasks unrelated to document generation.
dependencies
{"commands":["python3","node"],"tools":["skillScriptTool","skillFileTool"]}
platforms
["macos","linux","windows"]
> **Important:** All `scripts/` paths are relative to this skill directory. > Use `run_skill_script` tool to execute scripts, or run with: `cd {this_skill_dir} && python scripts/...` # DOCX creation, editing, and analysis ## Quick Start — Pick the Right Tool | Task | Recommended Tool | |------|------------------| | **Create** a new document (report / résumé / contract / memo) | `renderDocx()` — millisecond render, no subprocess | | **Edit** an existing .docx (content / formatting) | unpack → edit XML → pack workflow below | | Add tracked changes / comments | unpack → edit XML → pack workflow below | | GB/T 9704 official document | `writeGongwen()` (BmacClaw only) | ### Create a new document (recommended path) Call the in-process Java tool — no Node.js install, no fork, no disk round-trip: ``` renderDocx( markdown="# Title\n\nBody paragraph...", filename="monthly-report", pageSize="A4" ) ``` Returns a clickable link of the form `[monthly-report.docx](/api/v1/files/generated/<uuid>)` valid for 10 minutes. The user clicks it to download — no follow-up Agent step needed. `renderDocx` supports headings (`#` `##` `###`), bold (`**text**`), bullet lists (`- item`), numbered lists (`1. item`), pipe-style tables, and plain paragraphs. For images, headers/footers, or precise OOXML control, fall back to the docx-js workflow below. ## Prerequisites - **python-docx** (`pip install python-docx`): direct structure reading and light editing (paragraphs, styles, tables) - **docx** (`npm install -g docx`): new document creation - **LibreOffice** (`soffice`): `.doc` -> `.docx` conversion, tracked-changes acceptance, and PDF export - **pandoc**: text extraction - **pdftoppm** (poppler-utils): document-to-image workflows - If `pdftoppm` is unavailable, a Python fallback path may use `pdf2image`. - On Windows, dependencies must be installed and available in `PATH`; if missing, report the dependency issue and stop (do not keep retrying). ## Overview A .docx file is a ZIP archive containing XML files. ## Quick Reference | Task | Approach | |------|----------| | Read/analyze content | `pandoc` or unpack for raw XML | | Create new document | Use `docx-js` - see Creating New Documents below | | Edit existing document | Unpack → edit XML → repack - see Editing Existing Documents below | ### Converting .doc to .docx Legacy `.doc` files must be converted before editing: ```bash python scripts/office/soffice.py --headless --convert-to docx document.doc ``` ### Reading Content **Option A: python-docx (recommended for structured access)** Install: `pip install python-docx`. Gives direct access to paragraphs, styles, tables, and metadata without unpacking ZIP. ```python from docx import Document doc = Document("document.docx") # Paragraphs with styles for para in doc.paragraphs: print(f"[{para.style.name}] {para.text}") # Tables for i, table in enumerate(doc.tables): print(f"Table {i+1}:") for row in table.rows: print([cell.text for cell in row.cells]) # Inline styles within a paragraph for para in doc.paragraphs: for run in para.runs: print(f" run: bold={run.bold} italic={run.italic} text={run.text!r}") ``` Use python-docx when you need to read or lightly modify content. Fall back to the unpack/XML workflow for complex structural changes. **Option B: pandoc (plain text extraction)** ```bash # Text extraction with tracked changes pandoc --track-changes=all document.docx -o output.md # Raw XML access python scripts/office/unpack.py document.docx unpacked/ ``` ### Converting to Images ```bash python scripts/office/soffice.py --headless --convert-to pdf document.docx pdftoppm -jpeg -r 150 document.pdf page ``` ### Accepting Tracked Changes To produce a clean document with all tracked changes accepted (requires LibreOffice): ```bash python scripts/accept_changes.py input.docx output.docx ``` --- ## Creating New Documents Generate .docx files with JavaScript, then validate. Install: `npm install -g docx` ### Setup ```javascript const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink, TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType, VerticalAlign, PageNumber, PageBreak } = require('docx'); const doc = new Document({ sections: [{ children: [/* content */] }] }); Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer)); ``` ### Validation After creating the file, validate it. If validation fails, unpack, fix the XML, and repack. ```bash python scripts/office/validate.py doc.docx ``` ### Page Size ```javascript // CRITICAL: docx-js defaults to A4, not US Letter // Always set page size explicitly for consistent results sections: [{ properties: { page: { size: { width: 12240, // 8.5 inches in DXA height: 15840 // 11 inches in DXA }, margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 inch margins } }, children: [/* content */] }] ``` **Common page sizes (DXA units, 1440 DXA = 1 inch):** | Paper | Width | Height | Content Width (1" margins) | |-------|-------|--------|---------------------------| | US Letter | 12,240 | 15,840 | 9,360 | | A4 (default) | 11,906 | 16,838 | 9,026 | **Landscape orientation:** docx-js swaps width/height internally, so pass portrait dimensions and let it handle the swap: ```javascript size: { width: 12240, // Pass SHORT edge as width height: 15840, // Pass LONG edge as height orientation: PageOrientation.LANDSCAPE // docx-js swaps them in the XML }, // Content width = 15840 - left margin - right margin (uses the long edge) ``` ### Styles (Override Built-in Headings) Use Arial as the default font (universally supported). Keep titles black for readability. ```javascript const doc = new Document({ styles: { default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt default paragraphStyles: [ // IMPORTANT: Use exact IDs to override built-in styles { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true, run: { size: 32, bold: true, font: "Arial" }, paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel required for TOC { id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true, run: { size: 28, bold: true, font: "Arial" }, paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } }, ] }, sections: [{ children: [ new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] }), ] }] }); ``` ### Lists (NEVER use unicode bullets) ```javascript // CORRECT - use numbering config with LevelFormat.BULLET const doc = new Document({ numbering: { config: [ { reference: "bullets", levels: [{ level: 0, format: LevelFormat.BULLET, text: "\u2022", alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, { reference: "numbers", levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, ] }, sections: [{ children: [ new Paragraph({ numbering: { reference: "bullets", level: 0 }, children: [new TextRun("Bullet item")] }), new Paragraph({ numbering: { reference: "numbers", level: 0 }, children: [new TextRun("Numbered item")] }), ] }] }); // Each reference creates INDEPENDENT numbering // Same reference = continues (1,2,3 then 4,5,6) // Different reference = restarts (1,2,3 then 1,2,3) ``` ### Tables **CRITICAL: Tables need dual widths** - set both `columnWidths` on the table AND `width` on each cell. ```javascript // CRITICAL: Use ShadingType.CLEAR (not SOLID) to prevent black backgrounds const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }; const borders = { top: border, bottom: border, left: border, right: border }; new Table({ width: { size: 9360, type: WidthType.DXA }, // Always use DXA columnWidths: [4680, 4680], // Must sum to table width (DXA: 1440 = 1 inch) rows: [ new TableRow({ children: [ new TableCell({ borders, width: { size: 4680, type: WidthType.DXA }, // Also set on each cell shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR not SOLID margins: { top: 80, bottom: 80, left: 120, right: 120 }, children: [new Paragraph({ children: [new TextRun("Cell")] })] }) ] }) ] }) ``` **Width rules:** - **Always use `WidthType.DXA`** - never `WidthType.PERCENTAGE` - Table width must equal the sum of `columnWidths` - Cell `width` must match corresponding `columnWidth` ### Images ```javascript // CRITICAL: type parameter is REQUIRED new Paragraph({ children: [new ImageRun({ type: "png", // Required: png, jpg, jpeg, gif, bmp, svg data: fs.readFileSync("image.png"), transformation: { width: 200, height: 150 }, altText: { title: "Title", description: "Desc", name: "Name" } // All three required })] }) ``` ### Page Breaks ```javascript // PageBreak must be inside a Paragraph new Paragraph({ children: [new PageBreak()] }) ``` ### Table of Contents ```javascript // Headings must use HeadingLevel ONLY - no custom styles new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" }) ``` ### Headers/Footers ```javascript sections: [{ properties: { page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } }, headers: { default: new Header({ children: [new Paragraph({ children: [new TextRun("Header")] })] }) }, footers: { default: new Footer({ children: [new Paragraph({ children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] })] })] }) }, children: [/* content */] }] ``` ### Critical Rules for docx-js - **Set page size explicitly** - docx-js defaults to A4 - **Landscape: pass portrait dimensions** - docx-js swaps width/height internally - **Never use `\n`** - use separate Paragraph elements - **Never use unicode bullets** - use `LevelFormat.BULLET` with numbering config - **PageBreak must be in Paragraph** - **ImageRun requires `type`** - **Always set table `width` with DXA** - never use `WidthType.PERCENTAGE` - **Tables need dual widths** - `columnWidths` array AND cell `width` - **Use `ShadingType.CLEAR`** - never SOLID for table shading - **TOC requires HeadingLevel only** - **Override built-in styles** - use exact IDs: "Heading1", "Heading2", etc. - **Include `outlineLevel`** - required for TOC (0 for H1, 1 for H2, etc.) --- ## Editing Existing Documents **Follow all 3 steps in order.** ### Step 1: Unpack ```bash python scripts/office/unpack.py document.docx unpacked/ ```
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub