feat: make patch_xml respect custom Jinja2 delimiters#651
Conversation
patch_xml() had hardcoded regex patterns for {{ }}, {% %}, and {# #},
ignoring any custom delimiters set via jinja_env. This caused template
variables to be silently left unreplaced when using non-default delimiters
(like single braces { }) because XML tags split by Word were never stripped
from inside the custom blocks.
Changes:
- Added jinja_env parameter to patch_xml() and all its call sites
- Dynamic regex patterns for stripping XML tags inside Jinja2 blocks (pattern ②)
- Dynamic regex patterns for HTML entity cleanup inside Jinja2 tags (pattern ⑥)
- Default behavior unchanged when jinja_env is None
- Added test with intentionally split XML runs and custom { } delimiters
Co-Authored-By: Claude <noreply@anthropic.com>
|
Nice to see test runner compatibility work. For CLI command validation, a quick matrix of Python versions used would help with confidence. |
|
Thanks for the review, @arturict!
Python Version Compatibility MatrixI've tested this PR across all Python versions supported by the project (
The 4 skipped tests on 3.7/3.8 ( Regarding CLI Command ValidationThe custom delimiter feature is exercised through the Python API (via the
The current CLI ( Let me know if there's anything else you'd like me to address! |
Problem
patch_xml()has hardcoded regex patterns that only recognize default Jinja2 delimiters ({{ }},{% %},{# #}). When users configure custom delimiters viajinja_env:…the
patch_xmlpreprocessing step silently skips over their template variables. Specifically:Pattern ② (striptags — the core issue): Strips XML tags from inside
{{...}}/{%...%}/{#...#}blocks. Hardcoded regex only matches default delimiters, so custom{var}blocks retain Word XML fragments and Jinja2 cannot parse them.Pattern ⑥ (clean_tags): HTML entity cleanup inside Jinja2 tags. Same hardcoded pattern.
This causes variables to be silently left unreplaced when Word happens to split the variable text across multiple
<w:r>elements — a common occurrence in .docx files.Root Cause
Changes
patch_xml: Addedjinja_env=Noneparameter. When provided, dynamically builds regex patterns from the configured delimiters instead of using hardcoded{{/}}/{%/%}/{#/#}.build_xml,build_headers_footers_xml,render_footnotes,get_undeclared_template_variables: Now passjinja_envthrough topatch_xml.jinja_env=None, falls back to standard delimiters — fully backward compatible.tests/custom_delimiters.py: New test with intentionally split XML runs and custom{ }delimiters.Scope
This PR handles the two patterns that directly affect user template variables (② striptags, ⑥ clean_tags). docxtpl's own DSL tags (
colspan,cellbg,vm,hm,{{y ...}},{%y ... %},{%-,-%},{{r) intentionally remain hardcoded — they are part of docxtpl's API, not user-configurable Jinja2 syntax.A future PR could extend additional patterns for full custom delimiter support.
Co-Authored-By: Claude noreply@anthropic.com