This repository has been archived on 2023-08-07. You can view files and clone it, but cannot push or open issues or pull requests.
temple/lib/temple/html_to_temple.ex

77 lines
1.8 KiB
Elixir

defmodule Temple.HtmlToTemple do
@moduledoc false
@tags Temple.Html.void_elements() ++
Temple.Html.nonvoid_elements() ++ Temple.Svg.elements() ++ [:html]
def parse(doc) do
result =
doc
|> Floki.parse()
|> List.wrap()
|> Enum.map(&do_parse(&1, 0))
|> Enum.join("\n")
{:ok, result}
end
def do_parse({tag, [], []}, indent) do
tag = tag |> find_tag
(Temple.Utils.kebab_to_snake(tag) <> "()\n") |> pad_indent(indent)
end
def do_parse({tag, attrs, []}, indent) do
tag = tag |> find_tag
(Temple.Utils.kebab_to_snake(tag) <> build_attrs(attrs) <> "\n") |> pad_indent(indent)
end
def do_parse({tag, attrs, [""]}, indent), do: do_parse({tag, attrs, []}, indent)
def do_parse({tag, attrs, children}, indent) do
tag = tag |> find_tag
head =
(Temple.Utils.kebab_to_snake(tag) <> build_attrs(attrs) <> " do\n")
|> pad_indent(indent)
parsed_childs =
for child <- children do
do_parse(child, indent + 1)
end
|> Enum.join("\n")
head <> parsed_childs <> pad_indent("end\n", indent)
end
def do_parse(text, indent) when is_binary(text) do
(~s|text "| <> text <> ~s|"\n|) |> pad_indent(indent)
end
defp build_attrs([]), do: ""
defp build_attrs(attrs) do
attrs =
for {key, value} <- attrs do
wrap_in_quotes(key) <> ~s|: "| <> value <> ~s|"|
end
|> Enum.join(", ")
" " <> attrs
end
defp wrap_in_quotes(key) do
if Regex.match?(~r/[^a-zA-Z_]/, key) do
~s|"| <> key <> ~s|"|
else
key
end
end
defp pad_indent(paddable, indent) do
String.pad_leading(paddable, 2 * indent + String.length(paddable))
end
defp find_tag(tag),
do: @tags |> Enum.find(fn x -> String.downcase(to_string(x)) == tag end)
end