Skip to content

Commit

Permalink
don't replace percent when it is not the first non-whitespace character
Browse files Browse the repository at this point in the history
  • Loading branch information
cocolato committed Jan 26, 2024
1 parent ab8e747 commit db93097
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 13 deletions.
29 changes: 25 additions & 4 deletions mako/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ def parse(self):
continue
if self.match_python_block():
continue
if self.match_percent():
continue
if self.match_text():
continue

Expand Down Expand Up @@ -352,18 +354,37 @@ def match_end(self):
else:
return True

def match_percent(self):
match = self.match(r"([^%]*?)%(%+)", re.S)
if match:
text = match.group(1)
if text:
self.append_node(parsetree.Text, text)
for char in text[::-1]: # Look back, check wheither '%'
# is the first non-whitespace character in a line
if char == "\n":
break
elif char in ("\t", " "):
continue
else:
self.append_node(parsetree.Text, "%")
break
self.append_node(parsetree.Text, match.group(2))
else:
self.append_node(parsetree.Text, "%")
return True
else:
return False

def match_text(self):
match = self.match(
r"""
(.*?) # anything, followed by:
(
(?<=\n)(?=[ \t]*(?=%(?!%)|\#\#)) # an eval or line-based
(?<=\n)(?=[ \t]*(?=%|\#\#)) # an eval or line-based
# comment, preceded by a
# consumed newline and whitespace
|
(?<!%)(?=%%+) # consume the first percent sign
# out of a group of percent signs
|
(?=\${) # an expression
|
(?=</?[%&]) # a substitution or block or call start or end
Expand Down
70 changes: 61 additions & 9 deletions test/test_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,11 @@ def test_percent_escape(self):
TemplateNode(
{},
[
Text("""\n\n""", (1, 1)),
Text("""% some whatever.\n\n """, (3, 2)),
Text("% more some whatever\n", (5, 6)),
Text("\n\n", (1, 1)),
Text("%", (1, 1)),
Text(" some whatever.\n\n ", (3, 3)),
Text("%", (3, 3)),
Text(" more some whatever\n", (5, 7)),
ControlLine("if", "if foo:", False, (6, 1)),
ControlLine("if", "endif", True, (7, 1)),
Text(" ", (8, 1)),
Expand All @@ -222,11 +224,12 @@ def test_percent_escape2(self):
TemplateNode(
{},
[
Text("% do something\n", (1, 2)),
Text(
"%% do something\nif <some condition>:\n ", (2, 2)
),
Text("%%% do something\n ", (4, 6)),
Text("%", (1, 1)),
Text(" do something\n", (1, 3)),
Text("%%", (1, 3)),
Text(" do something\nif <some condition>:\n ", (2, 4)),
Text("%%%", (2, 4)),
Text(" do something\n ", (4, 9)),
],
),
)
Expand All @@ -246,14 +249,63 @@ def test_percent_escape_with_control_block(self):
Text("\n", (1, 1)),
ControlLine("for", "for i in [1, 2, 3]:", False, (2, 1)),
Text(" ", (3, 1)),
Text("% do something ", (3, 6)),
Text("%", (3, 1)),
Text(" do something ", (3, 7)),
Expression("i", [], (3, 21)),
Text("\n", (3, 25)),
ControlLine("for", "endfor", True, (4, 1)),
],
),
)

def test_inline_percent(self):
template = """
%% foo
bar %% baz
"""
node = Lexer(template).parse()
self._compare(
node,
TemplateNode(
{},
[
Text("\n", (1, 1)),
Text("%", (1, 1)),
Text(" foo\nbar ", (2, 3)),
Text("%", (2, 3)),
Text("%", (2, 3)),
Text(" baz\n", (3, 7)),
],
),
)

def test_inline_percent_with_control_block(self):
template = """
% for i in [1, 2, 3]:
%% foo
bar %% baz
% endfor
"""
node = Lexer(template).parse()
self._compare(
node,
TemplateNode(
{},
[
Text("\n", (1, 1)),
ControlLine(
"for", "for i in [1, 2, 3]:", False, (2, 1)
),
Text("%", (3, 1)),
Text(" foo\nbar ", (3, 3)),
Text("%", (3, 3)),
Text("%", (3, 3)),
Text(" baz\n", (4, 7)),
ControlLine("for", "endfor", True, (5, 1)),
],
),
)

def test_old_multiline_comment(self):
template = """#*"""
node = Lexer(template).parse()
Expand Down
18 changes: 18 additions & 0 deletions test/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -1699,3 +1699,21 @@ def test_percent_escape2(self):
" % do something 2",
" % do something 3",
]

def test_inline_percent(self):
t = Template(
"""
% for i in [1, 2, 3]:
%% foo
bar %% baz
% endfor
"""
)
assert result_raw_lines(t.render()) == [
"% foo",
"bar %% baz",
"% foo",
"bar %% baz",
"% foo",
"bar %% baz",
]

0 comments on commit db93097

Please sign in to comment.