diff --git a/lib/floki/raw_html.ex b/lib/floki/raw_html.ex index 1d1d1ab2..9e6f0f9d 100644 --- a/lib/floki/raw_html.ex +++ b/lib/floki/raw_html.ex @@ -36,6 +36,7 @@ defmodule Floki.RawHTML do def raw_html(html_tree, opts) do opts = Keyword.validate!(opts, encode: use_default_encoder?(), pretty: false) + html_tree = List.wrap(html_tree) encoder = case opts[:encode] do @@ -51,53 +52,36 @@ defmodule Floki.RawHTML do self_closing_tags = self_closing_tags() - IO.iodata_to_binary(build_raw_html(html_tree, [], encoder, padding, self_closing_tags)) + html_tree + |> build_raw_html([], encoder, padding, self_closing_tags) + |> Enum.reverse() + |> IO.iodata_to_binary() end - defp build_raw_html([], html, _encoder, _padding, _self_closing_tags), do: html + defp build_raw_html([], acc, _encoder, _padding, _self_closing_tags), do: acc - defp build_raw_html(string, _html, encoder, padding, _self_closing_tags) + defp build_raw_html([string | tail], acc, encoder, padding, self_closing_tags) when is_binary(string) do - leftpad_content(padding, encoder.(string)) + content = leftpad_content(padding, encoder.(string)) + acc = [content | acc] + build_raw_html(tail, acc, encoder, padding, self_closing_tags) end - defp build_raw_html(tuple, html, encoder, padding, self_closing_tags) when is_tuple(tuple), - do: build_raw_html([tuple], html, encoder, padding, self_closing_tags) - - defp build_raw_html([string | tail], html, encoder, padding, self_closing_tags) - when is_binary(string) do - build_raw_html( - tail, - [html, leftpad_content(padding, encoder.(string))], - encoder, - padding, - self_closing_tags - ) + defp build_raw_html([{:comment, comment} | tail], acc, encoder, padding, self_closing_tags) do + content = [leftpad(padding), ""] + acc = [content | acc] + build_raw_html(tail, acc, encoder, padding, self_closing_tags) end - defp build_raw_html([{:comment, comment} | tail], html, encoder, padding, self_closing_tags), - do: - build_raw_html( - tail, - [html, leftpad(padding), ""], - encoder, - padding, - self_closing_tags - ) - - defp build_raw_html([{:pi, tag, attrs} | tail], html, encoder, padding, self_closing_tags) do - build_raw_html( - tail, - [html, leftpad(padding), ""], - encoder, - padding, - self_closing_tags - ) + defp build_raw_html([{:pi, tag, attrs} | tail], acc, encoder, padding, self_closing_tags) do + content = [leftpad(padding), ""] + acc = [content | acc] + build_raw_html(tail, acc, encoder, padding, self_closing_tags) end defp build_raw_html( [{:doctype, type, public, system} | tail], - html, + acc, encoder, padding, self_closing_tags @@ -109,23 +93,40 @@ defmodule Floki.RawHTML do {public, system} -> [" PUBLIC \"", public, "\" \"", system | "\""] end - build_raw_html( - tail, - [html, leftpad(padding), ""], - encoder, - padding, - self_closing_tags - ) + content = [leftpad(padding), ""] + acc = [content | acc] + build_raw_html(tail, acc, encoder, padding, self_closing_tags) end - defp build_raw_html([{type, attrs, children} | tail], html, encoder, padding, self_closing_tags) do - build_raw_html( - tail, - [html | tag_for(type, attrs, children, encoder, padding, self_closing_tags)], - encoder, - padding, - self_closing_tags - ) + defp build_raw_html([{type, attrs, children} | tail], acc, encoder, padding, self_closing_tags) do + encoder = + case type do + "script" -> @no_encoder + "style" -> @no_encoder + "title" -> @no_encoder + _ -> encoder + end + + open_tag_content = [ + tag_with_attrs(type, attrs, children, padding, encoder, self_closing_tags), + line_ending(padding) + ] + + acc = [open_tag_content | acc] + + acc = + case children do + [] -> + acc + + _ -> + children = List.wrap(children) + build_raw_html(children, acc, encoder, pad_increase(padding), self_closing_tags) + end + + close_tag_content = close_end_tag(type, children, padding, self_closing_tags) + acc = [close_tag_content | acc] + build_raw_html(tail, acc, encoder, padding, self_closing_tags) end defp tag_attrs(attr_list, encoder) do @@ -171,29 +172,6 @@ defmodule Floki.RawHTML do defp build_attrs(attr, _encoder), do: [?\s, attr] - defp tag_for(type, attrs, children, encoder, padding, self_closing_tags) do - encoder = - case type do - "script" -> @no_encoder - "style" -> @no_encoder - "title" -> @no_encoder - _ -> encoder - end - - children_content = - case children do - [] -> "" - _ -> build_raw_html(children, "", encoder, pad_increase(padding), self_closing_tags) - end - - [ - tag_with_attrs(type, attrs, children, padding, encoder, self_closing_tags), - line_ending(padding), - children_content, - close_end_tag(type, children, padding, self_closing_tags) - ] - end - defp use_default_encoder? do Application.get_env(:floki, :encode_raw_html, true) end