Skip to content

Commit f1756a3

Browse files
authored
Merge pull request #1183 from exponea/1138-fix-unintended-lstrip-behavior-change
Fix unintended lstrip_blocks behavior
2 parents 4a70cd4 + 7163513 commit f1756a3

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

CHANGES.rst

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Unreleased
2525
:pr:`1178`
2626
- The special ``namespace()`` assignment object in templates works in
2727
async environments. :issue:`1180`
28+
- Fix whitespace being removed before tags in the middle of lines when
29+
``lstrip_blocks`` is enabled. :issue:`1138`
2830

2931

3032
Version 2.11.1

src/jinja2/lexer.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ def tokeniter(self, source, name, filename=None, state=None):
682682
balancing_stack = []
683683
lstrip_unless_re = self.lstrip_unless_re
684684
newlines_stripped = 0
685+
line_starting = True
685686

686687
while 1:
687688
# tokenizer loop
@@ -731,11 +732,11 @@ def tokeniter(self, source, name, filename=None, state=None):
731732
):
732733
# The start of text between the last newline and the tag.
733734
l_pos = text.rfind("\n") + 1
734-
735-
# If there's only whitespace between the newline and the
736-
# tag, strip it.
737-
if not lstrip_unless_re.search(text, l_pos):
738-
groups = (text[:l_pos],) + groups[1:]
735+
if l_pos > 0 or line_starting:
736+
# If there's only whitespace between the newline and the
737+
# tag, strip it.
738+
if not lstrip_unless_re.search(text, l_pos):
739+
groups = (text[:l_pos],) + groups[1:]
739740

740741
for idx, token in enumerate(tokens):
741742
# failure group
@@ -794,6 +795,8 @@ def tokeniter(self, source, name, filename=None, state=None):
794795
yield lineno, tokens, data
795796
lineno += data.count("\n")
796797

798+
line_starting = m.group()[-1:] == "\n"
799+
797800
# fetch new position into new variable so that we can check
798801
# if there is a internal parsing error which would result
799802
# in an infinite loop

tests/test_lexnparse.py

+92
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,98 @@ def test_lstrip_angle_bracket_compact(self, env):
729729
)
730730
assert tmpl.render(seq=range(5)) == "".join("%s\n" % x for x in range(5))
731731

732+
def test_lstrip_blocks_outside_with_new_line(self):
733+
env = Environment(lstrip_blocks=True, trim_blocks=False)
734+
tmpl = env.from_string(
735+
" {% if kvs %}(\n"
736+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
737+
" ){% endif %}"
738+
)
739+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
740+
assert out == "(\na=1 b=2 \n )"
741+
742+
def test_lstrip_trim_blocks_outside_with_new_line(self):
743+
env = Environment(lstrip_blocks=True, trim_blocks=True)
744+
tmpl = env.from_string(
745+
" {% if kvs %}(\n"
746+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
747+
" ){% endif %}"
748+
)
749+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
750+
assert out == "(\na=1 b=2 )"
751+
752+
def test_lstrip_blocks_inside_with_new_line(self):
753+
env = Environment(lstrip_blocks=True, trim_blocks=False)
754+
tmpl = env.from_string(
755+
" ({% if kvs %}\n"
756+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
757+
" {% endif %})"
758+
)
759+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
760+
assert out == " (\na=1 b=2 \n)"
761+
762+
def test_lstrip_trim_blocks_inside_with_new_line(self):
763+
env = Environment(lstrip_blocks=True, trim_blocks=True)
764+
tmpl = env.from_string(
765+
" ({% if kvs %}\n"
766+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
767+
" {% endif %})"
768+
)
769+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
770+
assert out == " (a=1 b=2 )"
771+
772+
def test_lstrip_blocks_without_new_line(self):
773+
env = Environment(lstrip_blocks=True, trim_blocks=False)
774+
tmpl = env.from_string(
775+
" {% if kvs %}"
776+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}"
777+
" {% endif %}"
778+
)
779+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
780+
assert out == " a=1 b=2 "
781+
782+
def test_lstrip_trim_blocks_without_new_line(self):
783+
env = Environment(lstrip_blocks=True, trim_blocks=True)
784+
tmpl = env.from_string(
785+
" {% if kvs %}"
786+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}"
787+
" {% endif %}"
788+
)
789+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
790+
assert out == " a=1 b=2 "
791+
792+
def test_lstrip_blocks_consume_after_without_new_line(self):
793+
env = Environment(lstrip_blocks=True, trim_blocks=False)
794+
tmpl = env.from_string(
795+
" {% if kvs -%}"
796+
" {% for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}"
797+
" {% endif -%}"
798+
)
799+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
800+
assert out == "a=1 b=2 "
801+
802+
def test_lstrip_trim_blocks_consume_before_without_new_line(self):
803+
env = Environment(lstrip_blocks=False, trim_blocks=False)
804+
tmpl = env.from_string(
805+
" {%- if kvs %}"
806+
" {%- for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}"
807+
" {%- endif %}"
808+
)
809+
out = tmpl.render(kvs=[("a", 1), ("b", 2)])
810+
assert out == "a=1 b=2 "
811+
812+
def test_lstrip_trim_blocks_comment(self):
813+
env = Environment(lstrip_blocks=True, trim_blocks=True)
814+
tmpl = env.from_string(" {# 1 space #}\n {# 2 spaces #} {# 4 spaces #}")
815+
out = tmpl.render()
816+
assert out == " " * 4
817+
818+
def test_lstrip_trim_blocks_raw(self):
819+
env = Environment(lstrip_blocks=True, trim_blocks=True)
820+
tmpl = env.from_string("{{x}}\n{%- raw %} {% endraw -%}\n{{ y }}")
821+
out = tmpl.render(x=1, y=2)
822+
assert out == "1 2"
823+
732824
def test_php_syntax_with_manual(self, env):
733825
env = Environment(
734826
"<?", "?>", "<?=", "?>", "<!--", "-->", lstrip_blocks=True, trim_blocks=True

0 commit comments

Comments
 (0)