
Docx Generator
Install docx-generator when you need to inspect Word (.docx) templates—paragraphs, tables, headers, and placeholders—before automating merges or agent-driven document fills.
Overview
docx-generator is an agent skill for the Build phase that analyzes DOCX templates and emits structured JSON of paragraphs, tables, and header/footer content for document automation planning.
Install
npx skills add https://github.com/jwynia/agent-skills --skill docx-generatorWhat is this skill?
- Deno CLI to unzip OOXML and parse document.xml for paragraphs and runs
- Extracts tables with row/col cell text and nested paragraph structure
- Surfaces headers, footers, list items, styles, and alignment metadata
- JSON output with optional pretty-print for downstream replacement planning
- Uses JSZip and DOMParser for in-repo template analysis without Microsoft Word
Adoption & trust: 692 installs on skills.sh; 92 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have a Word template for contracts or reports but cannot see placeholders, table layout, or section structure programmatically before building a merge pipeline.
Who is it for?
Builders automating proposals, invoices, or compliance docs from .docx templates who work in Deno/TypeScript and need a repeatable template audit step.
Skip if: One-off manual edits inside Word, PDF-only workflows, or teams that require full WYSIWYG authoring without touching OOXML.
When should I use this skill?
You need to analyze a .docx template structure (paragraphs, tables, headers/footers) before automated content replacement.
What do I get? / Deliverables
You receive a structured JSON inventory of paragraphs, tables, and headers/footers so you can define replacement rules or agent prompts against real template content.
- JSON export of paragraphs, tables, and header/footer text runs
- Template inventory suitable for replacement or prompt planning
Recommended Skills
Journey fit
Template analysis happens while producing specs, contracts, and handoff docs during the Build phase, before you ship customer-facing or legal artifacts. Docs subphase is where structured deliverables (proposals, SOWs, reports) are prepared and templated—not app UI code.
How it compares
Template structure analyzer for .docx—not a hosted document SaaS or a full mail-merge runtime by itself.
Common Questions / FAQ
Who is docx-generator for?
docx-generator is for solo and indie developers automating Word-based deliverables who need to extract text, tables, and placeholders from .docx files in CI or local Deno runs.
When should I use docx-generator?
Use it during Build → docs when onboarding a new client template, validating merge fields, or planning agent-driven document generation before shipping customer PDFs.
Is docx-generator safe to install?
The skill runs local read-only analysis on files you specify; review the Security Audits panel on this page and only point it at documents you are allowed to process.
SKILL.md
READMESKILL.md - Docx Generator
#!/usr/bin/env -S deno run --allow-read /** * analyze-template.ts - Extract text content and structure from DOCX files * * Extracts paragraphs, tables, headers, footers, and placeholders from Word documents * for template analysis and content replacement planning. * * Usage: * deno run --allow-read scripts/analyze-template.ts <input.docx> [options] * * Options: * -h, --help Show help * -v, --verbose Enable verbose output * --pretty Pretty-print JSON output * * Permissions: * --allow-read: Read DOCX file */ import { parseArgs } from "jsr:@std/cli@1.0.9/parse-args"; import { basename } from "jsr:@std/path@1.0.8"; import JSZip from "npm:jszip@3.10.1"; import { DOMParser } from "npm:@xmldom/xmldom@0.9.6"; // === Types === export interface TextRun { text: string; bold?: boolean; italic?: boolean; underline?: boolean; fontSize?: number; fontFamily?: string; color?: string; } export interface ParagraphInfo { index: number; style?: string; alignment?: "left" | "center" | "right" | "justify"; runs: TextRun[]; fullText: string; isListItem: boolean; listLevel?: number; } export interface TableCellInfo { row: number; col: number; text: string; paragraphs: ParagraphInfo[]; } export interface TableInfo { index: number; rows: number; cols: number; cells: TableCellInfo[]; } export interface HeaderFooterInfo { type: "header" | "footer"; section: "default" | "first" | "even"; paragraphs: ParagraphInfo[]; } export interface PlaceholderInfo { tag: string; location: string; paragraphIndex?: number; tableIndex?: number; cellLocation?: string; } export interface DocumentInventory { filename: string; paragraphCount: number; tableCount: number; imageCount: number; paragraphs: ParagraphInfo[]; tables: TableInfo[]; headersFooters: HeaderFooterInfo[]; placeholders: PlaceholderInfo[]; styles: string[]; } interface ParsedArgs { help: boolean; verbose: boolean; pretty: boolean; _: (string | number)[]; } // === Constants === const VERSION = "1.0.0"; const SCRIPT_NAME = "analyze-template"; const NS = { w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", }; // Placeholder pattern: {{PLACEHOLDER}} or ${placeholder} const PLACEHOLDER_REGEX = /\{\{([^}]+)\}\}|\$\{([^}]+)\}/g; // === Help Text === function printHelp(): void { console.log(` ${SCRIPT_NAME} v${VERSION} - Extract text content from DOCX templates Usage: deno run --allow-read scripts/${SCRIPT_NAME}.ts <input.docx> [options] Arguments: <input.docx> Path to the Word document to analyze Options: -h, --help Show this help message -v, --verbose Enable verbose output (to stderr) --pretty Pretty-print JSON output (default: compact) Examples: # Analyze document deno run --allow-read scripts/${SCRIPT_NAME}.ts template.docx > inventory.json # With verbose output deno run --allow-read scripts/${SCRIPT_NAME}.ts template.docx -v --pretty `); } // === Utility Functions === // deno-lint-ignore no-explicit-any function getElementsByTagNameNS(parent: any, ns: string, localName: string): any[] { const elements = parent.getElementsByTagNameNS(ns, localName); // deno-lint-ignore no-explicit-any return Array.from(elements) as any[]; } // deno-lint-ignore no-explicit-any function getTextContent(element: any): string { const textElements = getElementsByTagNameNS(element, NS.w, "t"); return textElements.map((t) => t.textContent || "").join(""); } // === Parsing Functions === // deno-lint-ignore no-explicit-any function parseTextRun(rElement: any): TextRun { const run: TextRun = { text: getTextContent(rElement), }; const rPr = getElementsByTagNameNS(rElement, NS.w, "rPr")[0]; if (rPr) { // Bold if (getElementsByTagNameNS(rPr, NS.w, "b").length > 0) { run.bold = true; } // Italic if (getElementsByTagN