diff --git a/tools/check-templates b/tools/check-templates index 1d71b2ce08..ebd1772b33 100755 --- a/tools/check-templates +++ b/tools/check-templates @@ -101,7 +101,7 @@ def check_html_templates(templates: Iterable[str], all_dups: bool, fix: bool) -> sys.exit(1) for fn in templates: - tokens = validate(fn) + tokens = validate(fn, template_format="django") if not validate_indent_html(fn, tokens, fix): sys.exit(1) @@ -111,7 +111,7 @@ def check_handlebars_templates(templates: Iterable[str], fix: bool) -> None: templates = [fn for fn in templates if fn.endswith(".hbs")] for fn in templates: - tokens = validate(fn) + tokens = validate(fn, template_format="handlebars") if not validate_indent_html(fn, tokens, fix): sys.exit(1) diff --git a/tools/lib/template_parser.py b/tools/lib/template_parser.py index 08dce7fb01..fb10c2f9a4 100644 --- a/tools/lib/template_parser.py +++ b/tools/lib/template_parser.py @@ -48,7 +48,7 @@ class Token: self.parent_token: Optional[Token] = None -def tokenize(text: str) -> List[Token]: +def tokenize(text: str, template_format: Optional[str] = None) -> List[Token]: in_code_block = False def advance(n: int) -> None: @@ -70,13 +70,13 @@ def tokenize(text: str) -> List[Token]: return looking_at("{{!") def looking_at_djangocomment() -> bool: - return looking_at("{#") + return template_format == "django" and looking_at("{#") def looking_at_handlebars_partial() -> bool: - return looking_at("{{>") + return template_format == "handlebars" and looking_at("{{>") def looking_at_handlebars_partial_block() -> bool: - return looking_at("{{#>") + return template_format == "handlebars" and looking_at("{{#>") def looking_at_html_start() -> bool: return looking_at("<") and not looking_at(" List[Token]: return looking_at("{{#") or looking_at("{{^") or looking_at("{{~#") def looking_at_handlebars_else() -> bool: - return looking_at("{{else") + return template_format == "handlebars" and looking_at("{{else") def looking_at_template_var() -> bool: return looking_at("{") def looking_at_handlebars_end() -> bool: - return looking_at("{{/") or looking_at("{{~/") + return template_format == "handlebars" and (looking_at("{{/") or looking_at("{{~/")) def looking_at_django_start() -> bool: - return looking_at("{% ") + return template_format == "django" and looking_at("{% ") def looking_at_django_else() -> bool: - return looking_at("{% else") or looking_at("{% elif") + return template_format == "django" and (looking_at("{% else") or looking_at("{% elif")) def looking_at_django_end() -> bool: - return looking_at("{% end") + return template_format == "django" and looking_at("{% end") def looking_at_jinja2_end_whitespace_stripped() -> bool: - return looking_at("{%- end") + return template_format == "django" and looking_at("{%- end") def looking_at_jinja2_start_whitespace_stripped_type2() -> bool: # This function detects tag like {%- if foo -%}...{% endif %} - return looking_at("{%-") and not looking_at("{%- end") + return template_format == "django" and looking_at("{%-") and not looking_at("{%- end") def looking_at_whitespace() -> bool: return looking_at("\n") or looking_at(" ") @@ -343,7 +343,11 @@ def tag_flavor(token: Token) -> Optional[str]: raise AssertionError(f"tools programmer neglected to handle {kind} tokens") -def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token]: +def validate( + fn: Optional[str] = None, + text: Optional[str] = None, + template_format: Optional[str] = None, +) -> List[Token]: assert fn or text if fn is None: @@ -356,7 +360,7 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token lines = text.split("\n") try: - tokens = tokenize(text) + tokens = tokenize(text, template_format=template_format) except FormattedError as e: raise TemplateParserError( f""" diff --git a/tools/tests/test_pretty_print.py b/tools/tests/test_pretty_print.py index 1766e66620..0e8a89a2c7 100644 --- a/tools/tests/test_pretty_print.py +++ b/tools/tests/test_pretty_print.py @@ -1,4 +1,5 @@ import unittest +from typing import Optional from tools.lib.pretty_print import pretty_print_html from tools.lib.template_parser import validate @@ -280,9 +281,9 @@ GOOD_HTML11 = """ """ -def pretty_print(html: str) -> str: +def pretty_print(html: str, template_format: Optional[str] = None) -> str: fn = "" - tokens = validate(fn=fn, text=html) + tokens = validate(fn=fn, text=html, template_format=template_format) return pretty_print_html(tokens, fn=fn) @@ -294,12 +295,12 @@ class TestPrettyPrinter(unittest.TestCase): self.compare(pretty_print(GOOD_HTML), GOOD_HTML) self.compare(pretty_print(BAD_HTML), GOOD_HTML) self.compare(pretty_print(BAD_HTML1), GOOD_HTML1) - self.compare(pretty_print(BAD_HTML2), GOOD_HTML2) + self.compare(pretty_print(BAD_HTML2, template_format="handlebars"), GOOD_HTML2) self.compare(pretty_print(BAD_HTML4), GOOD_HTML4) - self.compare(pretty_print(BAD_HTML5), GOOD_HTML5) + self.compare(pretty_print(BAD_HTML5, template_format="handlebars"), GOOD_HTML5) self.compare(pretty_print(BAD_HTML6), GOOD_HTML6) - self.compare(pretty_print(BAD_HTML7), GOOD_HTML7) - self.compare(pretty_print(BAD_HTML8), GOOD_HTML8) - self.compare(pretty_print(BAD_HTML9), GOOD_HTML9) - self.compare(pretty_print(BAD_HTML10), GOOD_HTML10) + self.compare(pretty_print(BAD_HTML7, template_format="handlebars"), GOOD_HTML7) + self.compare(pretty_print(BAD_HTML8, template_format="handlebars"), GOOD_HTML8) + self.compare(pretty_print(BAD_HTML9, template_format="handlebars"), GOOD_HTML9) + self.compare(pretty_print(BAD_HTML10, template_format="django"), GOOD_HTML10) self.compare(pretty_print(BAD_HTML11), GOOD_HTML11) diff --git a/tools/tests/test_template_parser.py b/tools/tests/test_template_parser.py index ef178b53d7..66d506a8ac 100644 --- a/tools/tests/test_template_parser.py +++ b/tools/tests/test_template_parser.py @@ -20,9 +20,10 @@ class ParserTest(unittest.TestCase): error: str, fn: Optional[str] = None, text: Optional[str] = None, + template_format: Optional[str] = None, ) -> None: with self.assertRaisesRegex(TemplateParserError, error): - validate(fn=fn, text=text) + validate(fn=fn, text=text, template_format=template_format) def test_is_django_block_tag(self) -> None: self.assertTrue(is_django_block_tag("block")) @@ -47,7 +48,7 @@ class ParserTest(unittest.TestCase):

{{stream}}

{{/with}} """ - validate(text=my_html) + validate(text=my_html, template_format="handlebars") def test_validate_handlebars_partial_block(self) -> None: my_html = """ @@ -55,7 +56,7 @@ class ParserTest(unittest.TestCase):

hello!

{{/generic_thing}} """ - validate(text=my_html) + validate(text=my_html, template_format="handlebars") def test_validate_bad_handlebars_partial_block(self) -> None: my_html = """ @@ -63,7 +64,9 @@ class ParserTest(unittest.TestCase):

hello!

{{# generic_thing}} """ - self._assert_validate_error("Missing end tag for the token at row 4 13!", text=my_html) + self._assert_validate_error( + "Missing end tag for the token at row 4 13!", text=my_html, template_format="handlebars" + ) def test_validate_comment(self) -> None: my_html = """ @@ -79,7 +82,7 @@ class ParserTest(unittest.TestCase):

bar

{% endif %} """ - validate(text=my_html) + validate(text=my_html, template_format="django") my_html = """ {% block "content" %} @@ -124,13 +127,18 @@ class ParserTest(unittest.TestCase): '''Tag missing "}}" at line 2 col 13:"{{# foo "''', text=my_html, + template_format="handlebars", ) def test_validate_incomplete_handlebars_tag_2(self) -> None: my_html = """ {{# foo } """ - self._assert_validate_error('Tag missing "}}" at line 2 col 13:"{{# foo }\n"', text=my_html) + self._assert_validate_error( + 'Tag missing "}}" at line 2 col 13:"{{# foo }\n"', + text=my_html, + template_format="handlebars", + ) def test_validate_incomplete_django_tag_1(self) -> None: my_html = """ @@ -140,13 +148,18 @@ class ParserTest(unittest.TestCase): '''Tag missing "%}" at line 2 col 13:"{% foo "''', text=my_html, + template_format="django", ) def test_validate_incomplete_django_tag_2(self) -> None: my_html = """ {% foo % """ - self._assert_validate_error('Tag missing "%}" at line 2 col 13:"{% foo %\n"', text=my_html) + self._assert_validate_error( + 'Tag missing "%}" at line 2 col 13:"{% foo %\n"', + text=my_html, + template_format="django", + ) def test_validate_incomplete_html_tag_1(self) -> None: my_html = """ @@ -230,7 +243,10 @@ class ParserTest(unittest.TestCase): this is foo {% endif %} """ - validate(text=my_html) + validate( + text=my_html, + template_format="django", + ) def test_validate_jinja2_whitespace_markers_2(self) -> None: my_html = """ @@ -238,7 +254,10 @@ class ParserTest(unittest.TestCase): this is foo {%- endif %} """ - validate(text=my_html) + validate( + text=my_html, + template_format="django", + ) def test_validate_jinja2_whitespace_markers_3(self) -> None: my_html = """ @@ -246,7 +265,10 @@ class ParserTest(unittest.TestCase): this is foo {% endif -%} """ - validate(text=my_html) + validate( + text=my_html, + template_format="django", + ) def test_validate_jinja2_whitespace_markers_4(self) -> None: my_html = """ @@ -254,7 +276,10 @@ class ParserTest(unittest.TestCase): this is foo {% endif %} """ - validate(text=my_html) + validate( + text=my_html, + template_format="django", + ) def test_validate_mismatch_jinja2_whitespace_markers_1(self) -> None: my_html = """ @@ -262,7 +287,11 @@ class ParserTest(unittest.TestCase): this is foo {%- if bar %} """ - self._assert_validate_error("Missing end tag", text=my_html) + self._assert_validate_error( + "Missing end tag", + text=my_html, + template_format="django", + ) def test_validate_jinja2_whitespace_type2_markers(self) -> None: my_html = """ @@ -270,7 +299,10 @@ class ParserTest(unittest.TestCase): this is foo {% endif %} """ - validate(text=my_html) + validate( + text=my_html, + template_format="django", + ) def test_tokenize(self) -> None: tag = "" @@ -303,41 +335,41 @@ class ParserTest(unittest.TestCase): self.assertEqual(token.tag, "a") tag = "{{#with foo}}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="handlebars")[0] self.assertEqual(token.kind, "handlebars_start") self.assertEqual(token.tag, "with") tag = "{{/with}}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="handlebars")[0] self.assertEqual(token.kind, "handlebars_end") self.assertEqual(token.tag, "with") tag = "{{#> compose_banner }}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="handlebars")[0] self.assertEqual(token.kind, "handlebars_partial_block") self.assertEqual(token.tag, "compose_banner") tag = "{% if foo %}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="django")[0] self.assertEqual(token.kind, "django_start") self.assertEqual(token.tag, "if") tag = "{% endif %}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="django")[0] self.assertEqual(token.kind, "django_end") self.assertEqual(token.tag, "if") tag = "{% if foo -%}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="django")[0] self.assertEqual(token.kind, "jinja2_whitespace_stripped_start") self.assertEqual(token.tag, "if") tag = "{%- endif %}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="django")[0] self.assertEqual(token.kind, "jinja2_whitespace_stripped_end") self.assertEqual(token.tag, "if") tag = "{%- if foo -%}bla" - token = tokenize(tag)[0] + token = tokenize(tag, template_format="django")[0] self.assertEqual(token.kind, "jinja2_whitespace_stripped_type2_start") self.assertEqual(token.tag, "if")