Metadata-Version: 2.4
Name: docxtpl-ng
Version: 0.2.0
Summary: Use a .docx file as a Jinja2 template.
Author-email: toxicphreAK <pentesting.laboratories@gmail.com>
Maintainer-email: toxicphreAK <pentesting.laboratories@gmail.com>
License-Expression: MIT
Project-URL: Changelog, https://github.com/toxicphreAK/docxtpl-ng/blob/main/HISTORY.md
Project-URL: Documentation, https://toxicphreak.github.io/docxtpl-ng/
Project-URL: Homepage, https://github.com/toxicphreAK/docxtpl-ng
Project-URL: Repository, https://github.com/toxicphreAK/docxtpl-ng
Project-URL: Bug Tracker, https://github.com/toxicphreAK/docxtpl-ng/issues
Keywords: docx,jinja2,office,openxml,template,word
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Office Suites
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Text Processing :: Markup
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: python-docx-ng>=2.0.0
Requires-Dist: jinja2>=3.1.2
Dynamic: license-file

# docxtpl-ng

[![PyPI](https://img.shields.io/pypi/v/docxtpl-ng)](https://pypi.org/project/docxtpl-ng/)
[![Downloads](https://img.shields.io/pypi/dm/docxtpl-ng)](https://pypistats.org/packages/docxtpl-ng)

Use a `.docx` file as a [Jinja2](https://jinja.palletsprojects.com/) template.

Design the document in Word — styles, tables, headers, page layout, the lot —
write `{{ customer.name }}` where the data goes, and render it from Python.

```python
from docxtpl import Template

tpl = Template("invoice.docx")
tpl.render({"customer": customer, "lines": lines, "total": total})
tpl.save("invoice-2026-0042.docx")
```

- Documentation: <https://toxicphreak.github.io/docxtpl-ng/>
- Repo: <https://github.com/toxicphreAK/docxtpl-ng>
- Releases: <https://github.com/toxicphreAK/docxtpl-ng/releases>
- PyPI: <https://pypi.org/project/docxtpl-ng/>

## Status

**Alpha.** The whole feature set is implemented and tested — 269 tests, with
rendered documents validated against the ISO/IEC 29500 schemas and compared
against what `docxtpl` itself produces — but it has not been run over a large
corpus of real templates or used in anger. The `0.` major says the same thing:
expect to find things, and expect the odd rough edge to be filed off in a way
that changes behaviour. Follow the
[milestones](https://github.com/toxicphreAK/docxtpl-ng/milestones) for
progress.

## Installing

```bash
pip install docxtpl-ng
```

or, with uv:

```bash
uv add docxtpl-ng
```

> Note: the importable package is `docxtpl`, not `docxtpl_ng` — use
> `import docxtpl`. `docxtpl-ng` and `docxtpl` therefore cannot be installed
> side by side.

Python 3.9 through 3.14. The only runtime dependencies are
[python-docx-ng](https://github.com/toxicphreAK/python-docx-ng) for the document
model and Jinja2 for the templating.

## Two APIs

`docxtpl-ng` exports two public surfaces over one engine.

**The modern API** — `Template`, `Text`, `Fragment`, `Image`, `Preformatted` —
is typed throughout and keyword-only where an argument is easy to misplace. Use
it for new code.

**The compatibility API** — `DocxTemplate`, `RichText`, `R`, `Subdoc`,
`InlineImage`, `Listing` — matches the names and signatures published by the
[`docxtpl`](https://pypi.org/project/docxtpl/) distribution. The package this
distribution installs is called `docxtpl` as well, so an existing project
migrates by swapping the dependency and changing nothing else:

```diff
-docxtpl>=0.16
+docxtpl-ng>=0.1.0
```

```python
from docxtpl import DocxTemplate, RichText, InlineImage  # unchanged
```

The two cannot be installed side by side — they claim the same import name — so
remove `docxtpl` first.

Your `.docx` templates need no changes at all: the tag dialect — `{{ var }}`,
`{%p %}`, `{%tr %}`, `{%tc %}`, `{%r %}`, `{% colspan %}`, `{% cellbg %}`,
`{% hm %}`, `{% vm %}` — is reproduced exactly. The compatibility surface is
supported indefinitely and is not deprecated.

## Relationship to `docxtpl`

`docxtpl` (repository `python-docx-template`) is the project that established
this idea, and it deserves the credit for it. `docxtpl-ng` is an independent
implementation, not a fork: it shares no code with it, and it is MIT licensed
rather than LGPL-2.1.

It exists because `docxtpl` depends on the `python-docx` *distribution*, which
cannot be installed alongside `python-docx-ng`, and because the LGPL made
absorbing it into the `-ng` suite impossible. Rewriting was the way to get a
templating layer that is part of the suite, permissively licensed, and built on
the typed element tree rather than on regular expressions over serialised XML.

## How it works

Four phases, of which only one sees text:

| Phase | What it does |
| --- | --- |
| 1. Coalesce | Merge adjacent runs Word split mid-tag, so `{{ cust`+`omer }}` is one tag again |
| 2. Compile | Hoist `{%tr %}`/`{%p %}` control tags onto the element they name; replace table directives with sentinels; serialise once |
| 3. Render | Jinja2, with XML autoescaping |
| 4. Rebuild | Re-parse into typed elements, expand `\n`/`\t`/`\f` into `w:br`/`w:tab`, resolve merges and shading against the real table |

Structural decisions are made where the schema is known, so a rendered document
is well-formed by construction. See
[docs/dev/architecture.md](docs/dev/architecture.md).

## Contributing

```bash
uv sync
uv run pytest -q
uv run ruff check .
```

Requires [uv](https://docs.astral.sh/uv/).

## Licence

MIT. See [LICENSE](LICENSE).
