ignore trim_blocks using '+%}'

This commit is contained in:
Amy 2020-06-17 14:12:57 -04:00 committed by David Lord
parent 9b718ed3d2
commit 6b0122768f
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
4 changed files with 136 additions and 5 deletions

View File

@ -13,7 +13,7 @@ Unreleased
:class:`~loaders.PackageLoader`. :issue:`1168`
- Fix a bug that caused imported macros to not have access to the
current template's globals. :issue:`688`
- Add ability to ignore ``trim_blocks`` using ``+%}``. :issue:`1036`
Version 2.11.2
--------------

View File

@ -230,6 +230,15 @@ plus sign (``+``) at the start of a block::
{%+ if something %}yay{% endif %}
</div>
Similarly, you can manually disable the ``trim_blocks`` behavior by
putting a plus sign (``+``) at the end of a block::
<div>
{% if something +%}
yay
{% endif %}
</div>
You can also strip whitespace in templates by hand. If you add a minus
sign (``-``) to the start or end of a block (e.g. a :ref:`for-loop` tag), a
comment, or a variable expression, the whitespaces before or after

View File

@ -509,8 +509,8 @@ class Lexer:
TOKEN_COMMENT_BEGIN: [
(
c(
fr"(.*?)((?:\-{comment_end_re}\s*"
fr"|{comment_end_re}){block_suffix_re})"
fr"(.*?)((?:\+{comment_end_re}|\-{comment_end_re}\s*"
fr"|{comment_end_re}{block_suffix_re}))"
),
(TOKEN_COMMENT, TOKEN_COMMENT_END),
"#pop",
@ -520,7 +520,10 @@ class Lexer:
# blocks
TOKEN_BLOCK_BEGIN: [
(
c(fr"(?:\-{block_end_re}\s*|{block_end_re}){block_suffix_re}"),
c(
fr"(?:\+{block_end_re}|\-{block_end_re}\s*"
fr"|{block_end_re}{block_suffix_re})"
),
TOKEN_BLOCK_END,
"#pop",
),
@ -540,7 +543,8 @@ class Lexer:
(
c(
fr"(.*?)((?:{block_start_re}(\-|\+|))\s*endraw\s*"
fr"(?:\-{block_end_re}\s*|{block_end_re}{block_suffix_re}))"
fr"(?:\+{block_end_re}|\-{block_end_re}\s*"
fr"|{block_end_re}{block_suffix_re}))"
),
OptionalLStrip(TOKEN_DATA, TOKEN_RAW_END),
"#pop",

View File

@ -903,3 +903,121 @@ ${item} ## the rest of the stuff
<!--- endfor -->"""
)
assert tmpl.render(seq=range(5)) == "01234"
class TestTrimBlocks:
def test_trim(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=False)
tmpl = env.from_string(" {% if True %}\n {% endif %}")
assert tmpl.render() == " "
def test_no_trim(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=False)
tmpl = env.from_string(" {% if True +%}\n {% endif %}")
assert tmpl.render() == " \n "
def test_no_trim_outer(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=False)
tmpl = env.from_string("{% if True %}X{% endif +%}\nmore things")
assert tmpl.render() == "X\nmore things"
def test_lstrip_no_trim(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(" {% if True +%}\n {% endif %}")
assert tmpl.render() == "\n"
def test_trim_blocks_false_with_no_trim(self, env):
# Test that + is a NOP (but does not cause an error) if trim_blocks=False
env = Environment(trim_blocks=False, lstrip_blocks=False)
tmpl = env.from_string(" {% if True %}\n {% endif %}")
assert tmpl.render() == " \n "
tmpl = env.from_string(" {% if True +%}\n {% endif %}")
assert tmpl.render() == " \n "
tmpl = env.from_string(" {# comment #}\n ")
assert tmpl.render() == " \n "
tmpl = env.from_string(" {# comment +#}\n ")
assert tmpl.render() == " \n "
tmpl = env.from_string(" {% raw %}{% endraw %}\n ")
assert tmpl.render() == " \n "
tmpl = env.from_string(" {% raw %}{% endraw +%}\n ")
assert tmpl.render() == " \n "
def test_trim_nested(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(
" {% if True %}\na {% if True %}\nb {% endif %}\nc {% endif %}"
)
assert tmpl.render() == "a b c "
def test_no_trim_nested(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(
" {% if True +%}\na {% if True +%}\nb {% endif +%}\nc {% endif %}"
)
assert tmpl.render() == "\na \nb \nc "
def test_comment_trim(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(""" {# comment #}\n\n """)
assert tmpl.render() == "\n "
def test_comment_no_trim(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(""" {# comment +#}\n\n """)
assert tmpl.render() == "\n\n "
def test_multiple_comment_trim_lstrip(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(
" {# comment #}\n\n{# comment2 #}\n \n{# comment3 #}\n\n "
)
assert tmpl.render() == "\n \n\n "
def test_multiple_comment_no_trim_lstrip(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string(
" {# comment +#}\n\n{# comment2 +#}\n \n{# comment3 +#}\n\n "
)
assert tmpl.render() == "\n\n\n \n\n\n "
def test_raw_trim_lstrip(self, env):
env = Environment(trim_blocks=True, lstrip_blocks=True)
tmpl = env.from_string("{{x}}{% raw %}\n\n {% endraw %}\n\n{{ y }}")
assert tmpl.render(x=1, y=2) == "1\n\n\n2"
def test_raw_no_trim_lstrip(self, env):
env = Environment(trim_blocks=False, lstrip_blocks=True)
tmpl = env.from_string("{{x}}{% raw %}\n\n {% endraw +%}\n\n{{ y }}")
assert tmpl.render(x=1, y=2) == "1\n\n\n\n2"
# raw blocks do not process inner text, so start tag cannot ignore trim
with pytest.raises(TemplateSyntaxError):
tmpl = env.from_string("{{x}}{% raw +%}\n\n {% endraw +%}\n\n{{ y }}")
def test_no_trim_angle_bracket(self, env):
env = Environment(
"<%", "%>", "${", "}", "<%#", "%>", lstrip_blocks=True, trim_blocks=True,
)
tmpl = env.from_string(" <% if True +%>\n\n <% endif %>")
assert tmpl.render() == "\n\n"
tmpl = env.from_string(" <%# comment +%>\n\n ")
assert tmpl.render() == "\n\n "
def test_no_trim_php_syntax(self, env):
env = Environment(
"<?",
"?>",
"<?=",
"?>",
"<!--",
"-->",
lstrip_blocks=False,
trim_blocks=True,
)
tmpl = env.from_string(" <? if True +?>\n\n <? endif ?>")
assert tmpl.render() == " \n\n "
tmpl = env.from_string(" <!-- comment +-->\n\n ")
assert tmpl.render() == " \n\n "