Packages
moon
2.78.3
2.90.5
retired
2.90.4
2.90.3
2.90.2
2.90.1
2.90.0
2.89.4
2.89.1
2.89.0
2.88.0
2.87.11
2.87.10
2.87.9
2.87.8
2.87.7
2.87.6
2.87.5
2.87.4
2.87.3
2.87.2
2.87.1
2.87.0
2.86.1
2.86.0
2.85.1
2.85.0
2.84.0
2.83.0
2.82.0
2.81.4
2.81.3
2.81.2
2.81.1
2.81.0
2.80.2
2.80.1
2.80.0
2.79.13
2.79.12
2.79.11
2.79.10
2.79.9
2.79.8
2.79.7
2.79.6
2.79.5
2.79.4
2.79.3
2.79.2
2.79.1
2.79.0
2.78.4
2.78.3
2.78.2
2.78.1
2.78.0
2.77.0
2.76.5
2.76.4
2.76.3
2.76.2
2.76.1
2.76.0
2.75.0
2.74.1
2.74.0
2.73.8
2.73.7
2.73.6
2.73.5
2.73.4
2.73.3
2.73.2
2.73.1
2.73.0
2.72.5
2.72.4
2.72.3
2.72.2
2.72.1
2.72.0
2.71.1
2.71.0
2.70.0
2.69.2
2.69.1
2.69.0
2.68.11
2.68.10
Components-based design system written in elixir
Current section
Files
Jump to
Current section
Files
lib/moon/helpers/tokens.ex
defmodule Moon.Helpers.Tokens do
@moduledoc "Some helper functions to proceed with html <-> tokens"
require Logger
@void_elements [
"area",
"base",
"br",
"col",
"command",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr"
]
@doc "Mostly copy of Surface.Compiler.to_ast/2 "
def prewalk(nodes, context, func) do
{for node <- List.wrap(nodes),
{result, context} = func.(node_type(node), node, context),
result != :ignore do
case result do
{type, attributes, children, node_meta} ->
{children, _context} = children |> prewalk(context, func)
{type, attributes, children, node_meta}
text when is_binary(text) ->
text
{:expr, expr, meta} ->
{:expr, expr, meta}
{:block, type, attributes, children, node_meta} ->
{children, _context} = children |> prewalk(context, func)
{:block, type, attributes, children, node_meta}
other ->
Logger.warning("Unknown tag: ")
dbg(other)
end
end, context}
end
def to_text(nodes, context \\ %{}) do
nodes
|> List.wrap()
|> Enum.reduce("", fn
string, text when is_binary(string) ->
"#{text}#{string}"
{type, attributes, [], _meta}, text ->
"#{text}<#{type} #{attrs_to_text(attributes)}/>"
{type, attributes, children, _meta}, text ->
"#{text}<#{type} #{attrs_to_text(attributes)}>#{to_text(children, context)}</#{type |> String.split(" ") |> hd()}>"
{:expr, expr, _meta}, text ->
"#{text}<%= #{expr} %>"
{:block, type, [{:root, {:attribute_expr, expr, _m2}, _m1} | other_attrs], children, _meta},
text ->
"#{text}<%= #{type} #{expr} #{attrs_to_text(other_attrs)} do %>#{to_text(children, context)}<% end %>"
end)
end
defp attrs_to_text(attrs) do
attrs
|> List.wrap()
|> Enum.map_join(" ", fn
{:root, {:attribute_expr, expr, _m2}, _m1} -> "{#{expr}}"
{:root, expr, _m1} -> expr
{name, {:attribute_expr, expr, _m2}, _m1} -> "#{name}={#{expr}}"
{name, expr, _m1} -> "#{name}=\"#{expr}\""
end)
end
# Slots
defp node_type({"#slot", _, _, _}), do: :slot
defp node_type({":" <> _, _, _, _}), do: :slot_entry
# Conditional blocks
defp node_type({:block, "if", _, _, _}), do: :if_elseif_else
defp node_type({:block, "elseif", _, _, _}), do: :if_elseif_else
defp node_type({:block, "else", _, _, _}), do: :else
defp node_type({:block, "unless", _, _, _}), do: :unless
# For
defp node_type({:block, "for", _, _, _}), do: :for_else
# case/match
defp node_type({:block, "case", _, _, _}), do: :block
defp node_type({:block, "match", _, _, _}), do: :sub_block
defp node_type({:block, :default, _, _, _}), do: :sub_block
defp node_type({:ast, _, _}), do: :ast
# Components
defp node_type({"#" <> _, _, _, _}), do: :macro_component
defp node_type({_, _, _, %{decomposed_tag: {:component, _, _}}}), do: :component
defp node_type({_, _, _, %{decomposed_tag: {:recursive_component, _, _}}}),
do: :recursive_component
defp node_type({_, _, _, %{decomposed_tag: {:remote, _, _}}}), do: :function_component
defp node_type({_, _, _, %{decomposed_tag: {:local, _, _}}}), do: :function_component
# HTML elements
defp node_type({name, _, _, _}) when name in @void_elements, do: :void_tag
defp node_type({_, _, _, _}), do: :tag
# Other
defp node_type({:expr, _, _}), do: :interpolation
defp node_type({:comment, _, _}), do: :comment
defp node_type(_), do: :text
end