From e3c5bd6fae4e6d7b169a027fea4d5f301d6b3784 Mon Sep 17 00:00:00 2001 From: Steffen Deusch Date: Fri, 20 Feb 2026 12:46:52 +0000 Subject: [PATCH] Strip EEx comments in parser when compiling templates Fixes #4144. When we simplified root tracking in #4125, we did not account for EEx comments (<%!-- ... --%>). Since those are just ignored in the compiler, we can already omit them at the tokenizer level. --- lib/phoenix_live_view/tag_engine.ex | 2 +- lib/phoenix_live_view/tag_engine/compiler.ex | 5 ----- lib/phoenix_live_view/tag_engine/parser.ex | 16 +++++++++++++--- test/phoenix_live_view/html_engine_test.exs | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/phoenix_live_view/tag_engine.ex b/lib/phoenix_live_view/tag_engine.ex index 78f1443a27..d336438fc2 100644 --- a/lib/phoenix_live_view/tag_engine.ex +++ b/lib/phoenix_live_view/tag_engine.ex @@ -44,7 +44,7 @@ defmodule Phoenix.LiveView.TagEngine do file: "nofile", engine: Phoenix.LiveView.Engine ]) - |> Keyword.merge(source: source, trim_eex: false) + |> Keyword.merge(source: source, trim_eex: false, strip_eex_comments: true) source |> TagEngine.Parser.parse!(options) diff --git a/lib/phoenix_live_view/tag_engine/compiler.ex b/lib/phoenix_live_view/tag_engine/compiler.ex index 9047cb839b..de30255caf 100644 --- a/lib/phoenix_live_view/tag_engine/compiler.ex +++ b/lib/phoenix_live_view/tag_engine/compiler.ex @@ -94,11 +94,6 @@ defmodule Phoenix.LiveView.TagEngine.Compiler do {state, substate} end - ## Skip EEx comments (<%!-- ... --%>) - defp handle_node({:eex_comment, _text}, substate, state) do - {state, substate} - end - ## HEEx interpolation {...} defp handle_node({:body_expr, expr, %{line: line, column: column}}, substate, state) do ast = Code.string_to_quoted!(expr, line: line, column: column, file: state.file) diff --git a/lib/phoenix_live_view/tag_engine/parser.ex b/lib/phoenix_live_view/tag_engine/parser.ex index 3c1b85d24d..7da8bd97eb 100644 --- a/lib/phoenix_live_view/tag_engine/parser.ex +++ b/lib/phoenix_live_view/tag_engine/parser.ex @@ -112,13 +112,19 @@ defmodule Phoenix.LiveView.TagEngine.Parser do file = Keyword.get(opts, :file, "nofile") indentation = Keyword.get(opts, :indentation, 0) trim_eex = Keyword.get(opts, :trim_eex, true) + strip_eex_comments = Keyword.get(opts, :strip_eex_comments, false) {:ok, eex_nodes} = EEx.tokenize(source, opts) {tokens, cont} = Enum.reduce( eex_nodes, {[], {:text, :enabled}}, - &do_tokenize(&1, &2, source, %{file: file, indentation: indentation, trim_eex: trim_eex}) + &do_tokenize(&1, &2, source, %{ + file: file, + indentation: indentation, + trim_eex: trim_eex, + strip_eex_comments: strip_eex_comments + }) ) Tokenizer.finalize(tokens, file, cont, source) @@ -134,8 +140,12 @@ defmodule Phoenix.LiveView.TagEngine.Parser do Tokenizer.tokenize(text, meta, tokens, cont, state) end - defp do_tokenize({:comment, text, meta}, {tokens, cont}, _contents, _opts) do - {[{:eex_comment, List.to_string(text), meta} | tokens], cont} + defp do_tokenize({:comment, text, meta}, {tokens, cont}, _contents, opts) do + if opts.strip_eex_comments do + {tokens, cont} + else + {[{:eex_comment, List.to_string(text), meta} | tokens], cont} + end end defp do_tokenize( diff --git a/test/phoenix_live_view/html_engine_test.exs b/test/phoenix_live_view/html_engine_test.exs index 73e17e9c45..bf95d172de 100644 --- a/test/phoenix_live_view/html_engine_test.exs +++ b/test/phoenix_live_view/html_engine_test.exs @@ -1432,6 +1432,7 @@ defmodule Phoenix.LiveView.HTMLEngineTest do assert eval(" ").root == true assert eval("\n\n\n").root == true + assert eval("<%!-- comment --%>\n\n\n").root == true end test "invalid cases" do