High-level block-based abstraction over python-docx for building dynamic Word documents in code.
Project description
docxblocks
🧱 High-level, block-based abstraction for python-docx.
🚀 Why docxblocks?
Unlike templating libraries like docxtpl, docxblocks keeps all logic in Python, not in .docx files. Build dynamic Word reports from structured block objects inside your codebase.
✨ Key Features
- Block types:
text,heading,table,bullets,image,page_break - Inline text by default - consecutive text blocks stay on the same line
- Smart newline handling -
\n\ncreates new paragraphs with blank lines - Style control via consistent
styledictionaries - Graceful fallback for missing data
- Declarative, testable, version-controlled
- No logic inside Word templates
📦 Installation
pip install docxblocks
📘 See the Style Guide for all supported style keys, color formats, and alignment options.
📄 Creating Word Templates
Important: Placeholder Requirements
Each placeholder MUST be in its own paragraph. This is crucial for proper document generation.
✅ Correct Template Structure:
Paragraph 1: {{main}}
Paragraph 2: (empty or other content)
Paragraph 3: {{header}}
❌ Incorrect Template Structure:
Paragraph 1: Some text {{main}} more text
Paragraph 2: {{header}} and other content
How to Create Templates:
- Open Microsoft Word and create a new document
- Add placeholders by typing them in separate paragraphs:
- Type
{{main}}and press Enter - Type
{{header}}and press Enter - Each placeholder gets its own paragraph
- Type
- Save as
.docxformat - Use in your code with
DocxBuilder("template.docx")
Template Example:
Document Title
{{header}}
{{main}}
{{footer}}
🧱 Block-Based API (Core Concept)
Each piece of content is a block:
{
"type": "text",
"text": "All systems operational.",
"style": {
"bold": True,
"italic": False,
"font_color": "007700",
"align": "center",
"style": "Normal"
}
}
Text Block Newline Behavior
Text blocks have intelligent newline handling:
- Single
\n: Remains as literal newline character (inline) - Double
\n\n: Creates a new paragraph with a blank line before it - Mixed usage: Works seamlessly with both patterns
{"type": "text", "text": "Line 1\nLine 2\n\nNew paragraph with blank line above."}
Table Cell Newline Behavior
Table cells also support the same intelligent newline handling:
- Single
\n: Remains as literal newline character within the cell - Double
\n\n: Creates new paragraphs with blank lines within the cell - Works in headers and data cells: Both header and row content support newline processing
{
"type": "table",
"content": {
"headers": ["Name", "Description\n\nDetails"],
"rows": [
["Item 1", "First paragraph.\n\nSecond paragraph with blank line."],
["Item 2", "Line 1\nLine 2\n\nNew paragraph."]
]
}
}
Block types:
| Type | Required Keys | Optional Keys |
|---|---|---|
text |
text |
new_paragraph |
heading |
text, level |
|
table |
content |
|
image |
path |
|
bullets |
items (list) |
|
page_break |
(none) |
Image Resizing
Images support automatic resizing with max_width and max_height constraints:
{
"type": "image",
"path": "chart.png",
"style": {
"max_width": "4in",
"max_height": "3in"
}
}
Features:
- Upscaling: Small images can be scaled up to meet size constraints
- Downscaling: Large images are scaled down to fit within constraints
- Aspect ratio preservation: Images maintain their original proportions
- Flexible constraints: Use either
max_width,max_height, or both - Multiple units: Supports inches (
"4in") and pixels ("300px")
🧪 Example
from docxblocks import DocxBuilder
builder = DocxBuilder("template.docx")
builder.insert("{{main}}", [
{"type": "heading", "text": "Summary", "level": 2},
{"type": "text", "text": "This report provides status."},
{
"type": "table",
"content": {
"headers": ["Service", "Status"],
"rows": [["API", "OK"], ["DB", "OK"]]
},
"style": {
"header_styles": {"bold": True, "bg_color": "f2f2f2"},
"column_widths": [0.5, 0.5]
}
},
{"type": "page_break"},
{"type": "image", "path": "chart.png", "style": {"max_width": "4in"}}
])
builder.save("output.docx")
🛠️ Philosophy
Keep the logic in your code — not in your Word template.
- Fully programmatic document generation
- No fragile embedded logic (
{{ if x }}) in.docx - Declarative, JSON-like format ideal for automation and templating
- Built for dynamic, testable, repeatable reports
🧪 Development
Setup
# Clone the repository
git clone https://github.com/frank-895/docxblocks.git
cd docxblocks
# Run the development setup script
./scripts/setup_dev.sh
Testing
# Run all tests
PYTHONPATH=. pytest tests
# Run tests with verbose output
PYTHONPATH=. pytest tests -v
# Run specific test file
PYTHONPATH=. pytest tests/test_text_block.py
Examples
# Run individual examples
cd examples
python text_block_example.py
python table_block_example.py
python image_block_example.py
python combined_example.py
python inline_text_example.py # Inline text functionality
python page_break_example.py # Page break functionality
python newline_example.py # Newline handling in text and tables
Continuous Integration
GitHub Actions automatically runs tests on:
- Every push to
mainanddevelopbranches - Every pull request to
main - Multiple Python versions (3.9, 3.10, 3.11)
Note: Tests run automatically in CI, so you can push your changes and see the results on GitHub.
📄 License
MIT - LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file docxblocks-1.3.1.tar.gz.
File metadata
- Download URL: docxblocks-1.3.1.tar.gz
- Upload date:
- Size: 21.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e445f9c42b2962556d2d275d9fe885430e5f4b289c7963c501de5622473158e
|
|
| MD5 |
bb607165d5b6ac8313abc0113ec8dd4a
|
|
| BLAKE2b-256 |
f4a8e002e67f092b8f17c05a8411d8a97c4f44291503204044aa0d1d7aeeacf4
|
Provenance
The following attestation bundles were made for docxblocks-1.3.1.tar.gz:
Publisher:
release.yml on frank-895/docxblocks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
docxblocks-1.3.1.tar.gz -
Subject digest:
0e445f9c42b2962556d2d275d9fe885430e5f4b289c7963c501de5622473158e - Sigstore transparency entry: 251656984
- Sigstore integration time:
-
Permalink:
frank-895/docxblocks@97477c9610053315407776ec820957af0fd33f8f -
Branch / Tag:
refs/tags/v1.3.1 - Owner: https://github.com/frank-895
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@97477c9610053315407776ec820957af0fd33f8f -
Trigger Event:
push
-
Statement type:
File details
Details for the file docxblocks-1.3.1-py3-none-any.whl.
File metadata
- Download URL: docxblocks-1.3.1-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d8674a4955a2fd9788cc6c2836e25e0a0ffef9d4b319c31673dcd669c657677
|
|
| MD5 |
aad2e16422dcd3e6f6749bf52e4257a0
|
|
| BLAKE2b-256 |
1d242a858df05908993b3ad0d6b8fbe3900a0bb75874e9ea7e533eb6365b5649
|
Provenance
The following attestation bundles were made for docxblocks-1.3.1-py3-none-any.whl:
Publisher:
release.yml on frank-895/docxblocks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
docxblocks-1.3.1-py3-none-any.whl -
Subject digest:
3d8674a4955a2fd9788cc6c2836e25e0a0ffef9d4b319c31673dcd669c657677 - Sigstore transparency entry: 251656985
- Sigstore integration time:
-
Permalink:
frank-895/docxblocks@97477c9610053315407776ec820957af0fd33f8f -
Branch / Tag:
refs/tags/v1.3.1 - Owner: https://github.com/frank-895
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@97477c9610053315407776ec820957af0fd33f8f -
Trigger Event:
push
-
Statement type: