Heex engine validates html. Some level of html validation is needed to avoid tag soup and clean code.
Consider the following snippet:
def div_wrapper_bug(assigns) do
assigns = assign_if_nil(assigns, :wrapper_class, nil)
~H"""
<%= if @wrapper_class do %>
<div class={@wrapper_class}> <!-- opening tag -->
<% end %>
<%= render_slot(@inner_block) %>
<%= if @wrapper_class do %>
</div> <!-- closing tag -->
<% end %>
"""
end
As you can see the above snippet will always produce valid html. But compilation will fail with below message:
** (Phoenix.LiveView.HTMLTokenizer.ParseError) lib/<YourProject>/form.ex:177:5: missing opening tag for </div>
(phoenix_live_view 0.17.5) lib/phoenix_live_view/html_engine.ex:227: Phoenix.LiveView.HTMLEngine.pop_tag!/2
(phoenix_live_view 0.17.5) lib/phoenix_live_view/html_engine.ex:432: Phoenix.LiveView.HTMLEngine.handle_token/2
(elixir 1.13.0) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix_live_view 0.17.5) lib/phoenix_live_view/html_engine.ex:86: Phoenix.LiveView.HTMLEngine.handle_end/1
(eex 1.13.0) lib/eex/compiler.ex:191: EEx.Compiler.wrap_expr/5
(eex 1.13.0) lib/eex/compiler.ex:140: EEx.Compiler.generate_buffer/4
(eex 1.13.0) lib/eex/compiler.ex:82: EEx.Compiler.generate_buffer/4
(phoenix_live_view 0.17.5) expanding macro: Phoenix.LiveView.Helpers.sigil_H/2
(<YourProject> 0.1.0) lib/<YourProject>/form.ex:171: Form.div_wrapper_bug/1
The below snippet will compile:
<%= if @wrapper_class do %>
<div class={@wrapper_class}>
<%= render_slot(@inner_block) %>
</div>
<% else %>
<%= render_slot(@inner_block) %>
<% end %>
The problem with workaround snippet is we will have to duplicate code. render_slot
is simplified example - it may be a html block.
I logged a bug on phoenix_live_view - it is closed as not a bug. Missing opening tag error when using `if` and closing tag is not present in same `if` block · Issue #1856 · phoenixframework/phoenix_live_view · GitHub
Discussion is about the heex engine’s html validation:
- what level of validation is needed - strict or loose, etc?
- what should be done in scenarios where a valid html is generated and but compiler is not sure 100% ?
- should it have configurations to treat certain kinds of errors as warnings
- should there be escape hatch (annotation) to disable validations on a block which produces valid html which is not understood by heex engine.
Please share your thoughts on it.
EDIT:
Jose updates on github issue.
- The escape hatch exists, you can render the tags dynamically:
<%= raw "<div ...>" %>
<%= raw "</div>" %>
- what cannot be done is to render the tags statically and conditionally.