docx skill: docx-js output has no default "Normal" paragraph style, breaks python-docx readers
Summary
When the docx skill generates a .docx via its docx-js code path (docx npm package, observed v9.7.1) without an explicit styles option, the resulting styles.xml has no "Normal" paragraph style at all — and no paragraph style is marked as the document default. Any tool built on python-docx that reads paragraph.style.name on an unstyled paragraph then crashes with AttributeError: 'NoneType' object has no attribute 'name', because python-docx's Styles.default(WD_STYLE_TYPE.PARAGRAPH) returns None when nothing is marked default — it does not fall back to Word's own w:docDefaults behavior.
Reproduction
const { Document, Paragraph, TextRun, Packer } = require("docx"); // v9.7.1
const doc = new Document({
sections: [{ children: [new Paragraph({ children: [new TextRun("hello")] })] }],
});
Packer.toBuffer(doc).then(buf => require("fs").writeFileSync("out.docx", buf));
Inspecting out.docx's word/styles.xml shows only Title, Heading1-6, Strong, ListParagraph, Hyperlink, FootnoteReference, FootnoteText, FootnoteTextChar, EndnoteReference, EndnoteText, EndnoteTextChar — no Normal, and nothing marked w:default="1" for a paragraph-type style. DefaultStylesFactory.newInstance() in this version of docx simply never emits one.
from docx import Document
d = Document("out.docx")
p = d.paragraphs[0]
p.style # None
p.style.name # AttributeError: 'NoneType' object has no attribute 'name'
Fix that works
Pass an explicit styles.paragraphStyles entry for "Normal" in the Document constructor, and set style: "Normal" on every Paragraph that isn't a heading/bullet (including paragraphs used as table-cell content or as empty spacers):
const doc = new Document({
styles: {
paragraphStyles: [{
id: "Normal", name: "Normal", quickFormat: true,
run: { font: "Calibri", size: 22 },
paragraph: { spacing: { line: 276 } },
}],
},
sections: [{ children: [new Paragraph({ style: "Normal", children: [new TextRun("hello")] })] }],
});
With every paragraph carrying an explicit w:pStyle, python-docx resolves paragraph.style.name correctly ("Normal").
Ask
Document this in the docx skill's SKILL.md "Creating with docx-js" gotchas (or fix DefaultStylesFactory upstream in the vendored docx package to always emit a default Normal style, matching what python-docx/Word themselves guarantee). This affects any downstream tooling built on python-docx that touches paragraph.style on docx-js output — not just a cosmetic styling gap.
Environment
docxnpm package v9.7.1, resolved via thedocxskill's own scratchpadnode_modulespython-docx(current PyPI release as of 2026-08)- Windows 11, Claude Code CLI