diff options
author | David Lord <davidism@gmail.com> | 2020-04-13 07:09:31 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-13 07:09:31 -0700 |
commit | f1756a3b44a6fd791954bd8d610cd9211d682518 (patch) | |
tree | d01904e74f2b795830f2e49f4941755903b0cb78 | |
parent | 4a70cd480f46da7004cc58b14be3b9966652954a (diff) | |
parent | 7163513a352cb7eda328fedb2bfcd987510929af (diff) | |
download | jinja-f1756a3b44a6fd791954bd8d610cd9211d682518.tar.gz |
Merge pull request #1183 from exponea/1138-fix-unintended-lstrip-behavior-change
Fix unintended lstrip_blocks behavior
-rw-r--r-- | CHANGES.rst | 2 | ||||
-rw-r--r-- | src/jinja2/lexer.py | 13 | ||||
-rw-r--r-- | tests/test_lexnparse.py | 92 |
3 files changed, 102 insertions, 5 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 579b80b9..e6608f45 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -25,6 +25,8 @@ Unreleased :pr:`1178` - The special ``namespace()`` assignment object in templates works in async environments. :issue:`1180` +- Fix whitespace being removed before tags in the middle of lines when + ``lstrip_blocks`` is enabled. :issue:`1138` Version 2.11.1 diff --git a/src/jinja2/lexer.py b/src/jinja2/lexer.py index 5fa940d9..552356a1 100644 --- a/src/jinja2/lexer.py +++ b/src/jinja2/lexer.py @@ -682,6 +682,7 @@ class Lexer(object): balancing_stack = [] lstrip_unless_re = self.lstrip_unless_re newlines_stripped = 0 + line_starting = True while 1: # tokenizer loop @@ -731,11 +732,11 @@ class Lexer(object): ): # The start of text between the last newline and the tag. l_pos = text.rfind("\n") + 1 - - # If there's only whitespace between the newline and the - # tag, strip it. - if not lstrip_unless_re.search(text, l_pos): - groups = (text[:l_pos],) + groups[1:] + if l_pos > 0 or line_starting: + # If there's only whitespace between the newline and the + # tag, strip it. + if not lstrip_unless_re.search(text, l_pos): + groups = (text[:l_pos],) + groups[1:] for idx, token in enumerate(tokens): # failure group @@ -794,6 +795,8 @@ class Lexer(object): yield lineno, tokens, data lineno += data.count("\n") + line_starting = m.group()[-1:] == "\n" + # fetch new position into new variable so that we can check # if there is a internal parsing error which would result # in an infinite loop diff --git a/tests/test_lexnparse.py b/tests/test_lexnparse.py index 3355791a..83ae75e0 100644 --- a/tests/test_lexnparse.py +++ b/tests/test_lexnparse.py @@ -729,6 +729,98 @@ ${item} ## the rest of the stuff ) assert tmpl.render(seq=range(5)) == "".join("%s\n" % x for x in range(5)) + def test_lstrip_blocks_outside_with_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string( + " {% if kvs %}(\n" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n" + " ){% endif %}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == "(\na=1 b=2 \n )" + + def test_lstrip_trim_blocks_outside_with_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string( + " {% if kvs %}(\n" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n" + " ){% endif %}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == "(\na=1 b=2 )" + + def test_lstrip_blocks_inside_with_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string( + " ({% if kvs %}\n" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n" + " {% endif %})" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == " (\na=1 b=2 \n)" + + def test_lstrip_trim_blocks_inside_with_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string( + " ({% if kvs %}\n" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n" + " {% endif %})" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == " (a=1 b=2 )" + + def test_lstrip_blocks_without_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string( + " {% if kvs %}" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}" + " {% endif %}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == " a=1 b=2 " + + def test_lstrip_trim_blocks_without_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string( + " {% if kvs %}" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}" + " {% endif %}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == " a=1 b=2 " + + def test_lstrip_blocks_consume_after_without_new_line(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string( + " {% if kvs -%}" + " {% for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}" + " {% endif -%}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == "a=1 b=2 " + + def test_lstrip_trim_blocks_consume_before_without_new_line(self): + env = Environment(lstrip_blocks=False, trim_blocks=False) + tmpl = env.from_string( + " {%- if kvs %}" + " {%- for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}" + " {%- endif %}" + ) + out = tmpl.render(kvs=[("a", 1), ("b", 2)]) + assert out == "a=1 b=2 " + + def test_lstrip_trim_blocks_comment(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string(" {# 1 space #}\n {# 2 spaces #} {# 4 spaces #}") + out = tmpl.render() + assert out == " " * 4 + + def test_lstrip_trim_blocks_raw(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string("{{x}}\n{%- raw %} {% endraw -%}\n{{ y }}") + out = tmpl.render(x=1, y=2) + assert out == "1 2" + def test_php_syntax_with_manual(self, env): env = Environment( "<?", "?>", "<?=", "?>", "<!--", "-->", lstrip_blocks=True, trim_blocks=True |