From 4e073ea451f56bda7847f381ead9bedfd136cd20 Mon Sep 17 00:00:00 2001 From: Staffan Malmgren Date: Mon, 28 Mar 2022 23:43:34 +0200 Subject: [PATCH] Added support for jinja comments for paragraphs and table rows+cells --- docxtpl/template.py | 14 ++++++++++---- tests/comments.py | 7 +++++++ tests/templates/comments.docx | Bin 0 -> 19085 bytes 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 tests/comments.py create mode 100644 tests/templates/comments.docx diff --git a/docxtpl/template.py b/docxtpl/template.py index 3c97202..79be84a 100644 --- a/docxtpl/template.py +++ b/docxtpl/template.py @@ -77,17 +77,17 @@ class DocxTemplate(object): strip all unnecessary xml tags, manage table cell background color and colspan, unescape html entities, etc... """ - # replace {{ by {{ ( works with {{ }} {% and %} ) - src_xml = re.sub(r'(?<={)(<[^>]*>)+(?=[\{%])|(?<=[%\}])(<[^>]*>)+(?=\})', '', + # replace {{ by {{ ( works with {{ }} {% and %} {# and #}) + src_xml = re.sub(r'(?<={)(<[^>]*>)+(?=[\{%\#])|(?<=[%\}\#])(<[^>]*>)+(?=\})', '', src_xml, flags=re.DOTALL) # replace {{jinja2 stuff}} by {{jinja2 stuff}} - # same thing with {% ... %} + # same thing with {% ... %} and {# #} # "jinja2 stuff" could a variable, a 'if' etc... anything jinja2 will understand def striptags(m): return re.sub('.*?(|]*>)', '', m.group(0), flags=re.DOTALL) - src_xml = re.sub(r'{%(?:(?!%}).)*|{{(?:(?!}}).)*', striptags, + src_xml = re.sub(r'{%(?:(?!%}).)*|{#(?:(?!#}).)*|{{(?:(?!}}).)*', striptags, src_xml, flags=re.DOTALL) # manage table cell colspan @@ -134,6 +134,12 @@ class DocxTemplate(object): pat = r'](?:(?!]).)*({%%|{{)%(y)s ([^}%%]*(?:%%}|}})).*?' % {'y': y} src_xml = re.sub(pat, r'\1 \2', src_xml, flags=re.DOTALL) + for y in ['tr', 'tc', 'p']: + # same thing, but for {#y xxx #} (but not where y == 'r', since that + # makes less sense to use comments in that context + pat = r'](?:(?!]).)*({#)%(y)s ([^}#]*(?:#})).*?' % {'y': y} + src_xml = re.sub(pat, r'\1 \2', src_xml, flags=re.DOTALL) + # add vMerge # use {% vm %} to make this table cell and its copies be vertically merged within a {% for %} def v_merge_tc(m): diff --git a/tests/comments.py b/tests/comments.py new file mode 100644 index 0000000..9fe6146 --- /dev/null +++ b/tests/comments.py @@ -0,0 +1,7 @@ +import sys, os +from docxtpl import DocxTemplate + +tpl = DocxTemplate('templates/comments.docx') + +tpl.render({}) +tpl.save('output/comments.docx') diff --git a/tests/templates/comments.docx b/tests/templates/comments.docx new file mode 100644 index 0000000000000000000000000000000000000000..d341babef2edea8580dcc594fdeff79447e54f69 GIT binary patch literal 19085 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