anthropics / anthropics/claude-code

docx skill: docx-js output has no default "Normal" paragraph style, breaks python-docx readers

Open Beginner friendly
#91,025 0 comments 0 reactions 0 assignees View on GitHub
area:skills bug platform:windows
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## 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

```js
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.

```python
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):

```js
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

- `docx` npm package v9.7.1, resolved via the `docx` skill's own scratchpad `node_modules`
- `python-docx` (current PyPI release as of 2026-08)
- Windows 11, Claude Code CLI

Contributor guide

No contributing guide indexed for this repository

Research direction

Find the docx skill's SKILL.md and its "Creating with docx-js" gotchas section mentioned in the issue. Read the reproduction and working fix, then add a note that docx-js output needs an explicit Normal paragraph style and explicit style on normal paragraphs for python-docx readers. Done means the gotcha is documented clearly with the affected versions/tools named.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js, python
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.