From d1cc807ee89616f939b3d4c82115e58f5fdde6a7 Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Thu, 25 Jan 2024 11:58:40 -0500 Subject: [PATCH] decode comprehensions --- lib/beacon/template/heex/heex_decoder.ex | 28 ++++++++++++++++++- .../template/heex/heex_decoder_test.exs | 13 +++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/beacon/template/heex/heex_decoder.ex b/lib/beacon/template/heex/heex_decoder.ex index 63bcc808..5f3f30ad 100644 --- a/lib/beacon/template/heex/heex_decoder.ex +++ b/lib/beacon/template/heex/heex_decoder.ex @@ -55,10 +55,15 @@ defmodule Beacon.Template.HEEx.HEExDecoder do ["<%!--", content, "--%>"] end - defp transform_node(%{"tag" => "eex_block", "blocks" => blocks, "arg" => arg}) do + defp transform_node(%{"tag" => "eex_block", "arg" => arg, "blocks" => blocks}) do ["<%=", arg, " %>", Enum.map(blocks, &transform_block/1)] end + # eex_block with a `for` comprehension + defp transform_node(%{"tag" => "eex_block", "arg" => arg, "ast" => ast}) do + ["<%= ", arg, " %>", decode_comprehension_ast(ast)] + end + defp transform_node(%{"tag" => tag, "attrs" => %{"self_close" => true} = attrs, "content" => []}) do attrs = Map.delete(attrs, "self_close") ["<", tag, " ", transform_attrs(attrs), "/>"] @@ -129,4 +134,25 @@ defmodule Beacon.Template.HEEx.HEExDecoder do defp reconstruct_attr({name, {:expr, content, _}, _}) do [name, "=", ?{, content, ?}] end + + defp decode_comprehension_ast(ast) do + ast + |> Jason.decode!() + |> List.flatten() + |> Enum.reduce([], fn node, acc -> decode_comprehension_ast_node(node, acc) end) + |> Enum.reverse() + end + + defp decode_comprehension_ast_node(%{"type" => "text", "content" => [content | _]}, acc) do + [content | acc] + end + + defp decode_comprehension_ast_node(%{"type" => "eex", "content" => [expr, %{"opt" => ~c"="}]}, acc) do + [["<%= ", expr, " %>"] | acc] + end + + # TODO: improve eex_block closing detection (maybe augment it in JSONEncoder) + defp decode_comprehension_ast_node("end", acc), do: ["<% end %>" | acc] + + defp decode_comprehension_ast_node(node, acc) when is_binary(node), do: [node | acc] end diff --git a/test/beacon/template/heex/heex_decoder_test.exs b/test/beacon/template/heex/heex_decoder_test.exs index e83e9bf1..8c3d2835 100644 --- a/test/beacon/template/heex/heex_decoder_test.exs +++ b/test/beacon/template/heex/heex_decoder_test.exs @@ -52,11 +52,14 @@ defmodule Beacon.Template.HEEx.HEExDecoderTest do end test "comprehensions" do - assert_equal(~S""" - <%= for val <- @beacon_live_data[:vals] do %> - <%= val %> - <% end %> - """) + assert_equal( + ~S""" + <%= for val <- @beacon_live_data[:vals] do %> + <%= val %> + <% end %> + """, + %{beacon_live_data: %{vals: [1]}} + ) end test "function components" do