aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmy <leiamy12@gmail.com>2020-06-17 14:12:57 -0400
committerDavid Lord <davidism@gmail.com>2020-06-22 10:21:47 -0700
commit6b0122768f2a5a1decba592e1758dba3c17abcf4 (patch)
tree2046b95d53a74b793dd54b7ea6e1b86724b93435
parent9b718ed3d26fc2f80ab58f3249b517a65db9cc7b (diff)
downloadjinja-6b0122768f2a5a1decba592e1758dba3c17abcf4.tar.gz
ignore trim_blocks using '+%}'
-rw-r--r--CHANGES.rst2
-rw-r--r--docs/templates.rst9
-rw-r--r--src/jinja2/lexer.py12
-rw-r--r--tests/test_lexnparse.py118
4 files changed, 136 insertions, 5 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index d42f213c..298cf0ab 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -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
--------------
diff --git a/docs/templates.rst b/docs/templates.rst
index a346ef23..3101d0ed 100644
--- a/docs/templates.rst
+++ b/docs/templates.rst
@@ -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
diff --git a/src/jinja2/lexer.py b/src/jinja2/lexer.py
index 0a992073..082a051d 100644
--- a/src/jinja2/lexer.py
+++ b/src/jinja2/lexer.py
@@ -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",
diff --git a/tests/test_lexnparse.py b/tests/test_lexnparse.py
index c0257cf1..96e134d1 100644
--- a/tests/test_lexnparse.py
+++ b/tests/test_lexnparse.py
@@ -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 "