104 lines
1.8 KiB
Elixir
104 lines
1.8 KiB
Elixir
defmodule Temple.Converter do
|
|
@moduledoc false
|
|
|
|
@boolean_attributes ~w[
|
|
allowfullscreen
|
|
async
|
|
autofocus
|
|
autoplay
|
|
checked
|
|
controls
|
|
default
|
|
defer
|
|
disabled
|
|
formnovalidate
|
|
ismap
|
|
itemscope
|
|
loop
|
|
multiple
|
|
muted
|
|
nomodule
|
|
novalidate
|
|
open
|
|
playsinline
|
|
readonly
|
|
required
|
|
reversed
|
|
selected
|
|
truespeed
|
|
]
|
|
|
|
def convert(html) do
|
|
html
|
|
|> Floki.parse_fragment!()
|
|
|> to_temple()
|
|
|> :erlang.iolist_to_binary()
|
|
|> Code.format_string!()
|
|
|> :erlang.iolist_to_binary()
|
|
end
|
|
|
|
def to_temple([]) do
|
|
[]
|
|
end
|
|
|
|
def to_temple([{tag, attrs, children} | rest]) do
|
|
[
|
|
to_string(tag),
|
|
" ",
|
|
to_temple_attrs(attrs),
|
|
" do\n",
|
|
to_temple(children),
|
|
"end\n"
|
|
] ++ to_temple(rest)
|
|
end
|
|
|
|
def to_temple([{:comment, comment} | rest]) do
|
|
[
|
|
comment
|
|
|> String.split("\n")
|
|
|> Enum.map_join("\n", fn line ->
|
|
if String.trim(line) != "" do
|
|
"# #{line}"
|
|
else
|
|
""
|
|
end
|
|
end),
|
|
"\n"
|
|
] ++ to_temple(rest)
|
|
end
|
|
|
|
def to_temple([text | rest]) when is_binary(text) do
|
|
[
|
|
text
|
|
|> String.split("\n")
|
|
|> Enum.map_join("\n", fn line ->
|
|
if String.trim(line) != "" do
|
|
escaped = String.replace(line, ~s|"|, ~s|\\"|)
|
|
~s|"#{String.trim(escaped)}"|
|
|
else
|
|
""
|
|
end
|
|
end),
|
|
"\n"
|
|
] ++ to_temple(rest)
|
|
end
|
|
|
|
defp to_temple_attrs([]) do
|
|
""
|
|
end
|
|
|
|
defp to_temple_attrs(attrs) do
|
|
Enum.map_join(attrs, ", ", fn
|
|
{attr, _value} when attr in @boolean_attributes ->
|
|
to_attr_name(attr) <> ": true"
|
|
|
|
{attr, value} ->
|
|
~s|#{to_attr_name(attr)}: "#{value}"|
|
|
end)
|
|
end
|
|
|
|
defp to_attr_name(name) do
|
|
String.replace(name, "-", "_")
|
|
end
|
|
end
|