From ba06fdbbc77898a721b17532d96ec20efb1f8429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= Date: Thu, 4 Jul 2024 10:54:36 +0900 Subject: [PATCH] jinja: support raw --- server/buildoutls/jinja.py | 16 +++++++++++++--- server/buildoutls/tests/test_jinja.py | 6 ++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/server/buildoutls/jinja.py b/server/buildoutls/jinja.py index 8be4749..5eb261c 100644 --- a/server/buildoutls/jinja.py +++ b/server/buildoutls/jinja.py @@ -13,6 +13,8 @@ class JinjaStatement(str, enum.Enum): Macro = "macro" Call = "call" Filter = "filter" + Raw = "raw" + EndRaw = "endraw" jinja_statements = set(JinjaStatement) @@ -46,6 +48,7 @@ def __init__(self) -> None: self.is_error = False self._stack: List[JinjaStatement] = [] self._current_line_was_in_jinja = False + self._in_raw = False self._in_comment = False self._in_multiline_expression = False self._in_multiline_statement = False @@ -54,7 +57,7 @@ def __init__(self) -> None: def feed(self, line: str) -> None: """Feeds a line and update the state.""" self._current_line_was_in_jinja = False - self.has_expression = bool(expression_re.search(line)) + self.has_expression = bool(expression_re.search(line)) and not self._in_raw expression_re_match = expression_re.search(line) if expression_re_match: if expression_re_match.start() == 0 and expression_re_match.end() == len( @@ -72,9 +75,13 @@ def feed(self, line: str) -> None: statement_match = statement_re.match(line) if statement_match: - self._current_line_was_in_jinja = True + self._current_line_was_in_jinja = not self._in_raw statement = statement_match.group("statement") - if statement in jinja_statements: + if statement == JinjaStatement.Raw: + self._in_raw = True + elif statement == JinjaStatement.EndRaw: + self._in_raw = False + elif statement in jinja_statements: self._stack.append(JinjaStatement(statement)) elif statement in end_block_statement: self.is_error = True @@ -82,6 +89,9 @@ def feed(self, line: str) -> None: popped = self._stack.pop() self.is_error = end_block_statement[statement] != popped + if self._in_raw: + return + if multiline_expression_start_re.match(line) or self._in_multiline_expression: self._current_line_was_in_jinja = True self._in_multiline_expression = multiline_expression_end_re.search(line) is None diff --git a/server/buildoutls/tests/test_jinja.py b/server/buildoutls/tests/test_jinja.py index 872ee4a..e515532 100644 --- a/server/buildoutls/tests/test_jinja.py +++ b/server/buildoutls/tests/test_jinja.py @@ -78,6 +78,12 @@ def test_is_in_jinja() -> None: ("line ", True), ("comment #}", True), ("after multi line comment", False), + # raw + ("{% raw %}", True), + ("in raw", False), + ("{% set jinja_ignored_in_raw = True %}", False), + ("{% endraw %}", True), + ("{% set jinja_detected_after_in_raw = True %}", True), ): parser.feed(line) assert parser.is_in_jinja == is_in_jinja