99cbb42962
This basically just adds svg elements as void and nonvoid element aliases and it works, will test on a real proejct before releasing the next release. Also, fixed the weird behaviour problem by defining types for each of the ast nodes and then referencing those types when defining the ast type. Unclear why this works, but I imagine it has to do with the types not being a big part of the compilation process or something. This also uses the typed_struct library to do so. Seems pretty slick and does what it claims it does.
97 lines
2.1 KiB
Elixir
97 lines
2.1 KiB
Elixir
defmodule Temple.Parser.Components do
|
|
@moduledoc false
|
|
@behaviour Temple.Parser
|
|
|
|
use TypedStruct
|
|
|
|
typedstruct do
|
|
field :function, function()
|
|
field :assigns, map()
|
|
field :children, [map()]
|
|
field :slots, [function()]
|
|
end
|
|
|
|
@impl true
|
|
def applicable?({:c, _, _}) do
|
|
true
|
|
end
|
|
|
|
def applicable?(_), do: false
|
|
|
|
@impl true
|
|
def run({:c, _meta, [component_function | args]}) do
|
|
{do_and_else, args} =
|
|
args
|
|
|> Temple.Parser.Utils.split_args()
|
|
|
|
{do_and_else, assigns} = Temple.Parser.Utils.consolidate_blocks(do_and_else, args)
|
|
|
|
{default_slot, {_, named_slots}} =
|
|
if children = do_and_else[:do] do
|
|
Macro.prewalk(
|
|
children,
|
|
{component_function, %{}},
|
|
fn
|
|
{:c, _, [name | _]} = node, {_, named_slots} ->
|
|
{node, {name, named_slots}}
|
|
|
|
{:slot, _, [name | args]} = node, {^component_function, named_slots} ->
|
|
{assigns, slot} = split_assigns_and_children(args, Macro.escape(%{}))
|
|
|
|
if is_nil(slot) do
|
|
{node, {component_function, named_slots}}
|
|
else
|
|
{nil,
|
|
{component_function, Map.put(named_slots, name, %{assigns: assigns, slot: slot})}}
|
|
end
|
|
|
|
node, acc ->
|
|
{node, acc}
|
|
end
|
|
)
|
|
else
|
|
{nil, {nil, %{}}}
|
|
end
|
|
|
|
children =
|
|
if default_slot == nil do
|
|
[]
|
|
else
|
|
Temple.Parser.parse(default_slot)
|
|
end
|
|
|
|
slots =
|
|
for {name, %{slot: slot, assigns: assigns}} <- named_slots do
|
|
Temple.Ast.new(
|
|
Temple.Parser.Slottable,
|
|
name: name,
|
|
content: Temple.Parser.parse(slot),
|
|
assigns: assigns
|
|
)
|
|
end
|
|
|
|
Temple.Ast.new(__MODULE__,
|
|
function: component_function,
|
|
assigns: assigns,
|
|
slots: slots,
|
|
children: children
|
|
)
|
|
end
|
|
|
|
defp split_assigns_and_children(args, empty) do
|
|
case args do
|
|
[assigns, [do: block]] ->
|
|
{assigns, block}
|
|
|
|
[[do: block]] ->
|
|
{empty, block}
|
|
|
|
[assigns] ->
|
|
{assigns, nil}
|
|
|
|
_ ->
|
|
{empty, nil}
|
|
end
|
|
end
|
|
end
|