diff --git a/lib/lazy_html.ex b/lib/lazy_html.ex index 358b37e..2bfed79 100644 --- a/lib/lazy_html.ex +++ b/lib/lazy_html.ex @@ -498,7 +498,9 @@ defmodule LazyHTML do """ @spec html_escape(String.t()) :: String.t() def html_escape(string) when is_binary(string) do - LazyHTML.Tree.append_escaped(string, "") + string + |> LazyHTML.Tree.append_escaped([]) + |> IO.iodata_to_binary() end # Access diff --git a/lib/lazy_html/tree.ex b/lib/lazy_html/tree.ex index 29edc32..ebd56c0 100644 --- a/lib/lazy_html/tree.ex +++ b/lib/lazy_html/tree.ex @@ -55,12 +55,11 @@ defmodule LazyHTML.Tree do def to_html(tree, opts \\ []) when is_list(tree) and is_list(opts) do opts = Keyword.validate!(opts, skip_whitespace_nodes: false) - # We build the html by continuously appending to a result binary. - # Appending to a binary is optimised by the runtime, so this - # approach is memory efficient. - ctx = %{skip_whitespace_nodes: opts[:skip_whitespace_nodes], escape: true} - to_html(tree, ctx, <<>>) + + tree + |> to_html(ctx, []) + |> IO.iodata_to_binary() end @void_tags ~w( @@ -73,17 +72,17 @@ defmodule LazyHTML.Tree do defp to_html([], _ctx, html), do: html defp to_html([{tag, attrs, children} | tree], ctx, html) do - html = <> + html = [html, ?<, tag] html = append_attrs(attrs, html) if tag in @void_tags do - html = <">> + html = [html, "/>"] to_html(tree, ctx, html) else - html = <">> + html = [html, ?>] escape_children = tag not in @no_escape_tags html = to_html(children, %{ctx | escape: escape_children}, html) - html = <">> + html = [html, "] to_html(tree, ctx, html) end end @@ -94,15 +93,16 @@ defmodule LazyHTML.Tree do end defp to_html([{:comment, content} | tree], ctx, html) do - to_html(tree, ctx, <">>) + html = [html, ""] + to_html(tree, ctx, html) end defp append_attrs([], html), do: html defp append_attrs([{name, value} | attrs], html) do - html = <> + html = [html, ?\s, name, ~S/="/] html = append_escaped(value, html) - html = <> + html = [html, ?"] append_attrs(attrs, html) end @@ -116,7 +116,7 @@ defmodule LazyHTML.Tree do defp append_text(<<_rest::binary>>, text, _whitespace_size, ctx, html) when not ctx.escape, - do: <> + do: [html, text] defp append_text(<>, text, whitespace_size, ctx, html) when ctx.escape, @@ -141,12 +141,12 @@ defmodule LazyHTML.Tree do defp append_escaped(<<>>, text, 0 = _offset, _size, html) do # We scanned the whole text and there were no characters to escape, # so we append the whole text. - <> + [html, text] end defp append_escaped(<<>>, text, offset, size, html) do chunk = binary_part(text, offset, size) - <> + [html, chunk] end escapes = [ @@ -160,7 +160,7 @@ defmodule LazyHTML.Tree do for {char, escaped} <- escapes do defp append_escaped(<>, text, offset, size, html) do chunk = binary_part(text, offset, size) - html = <> + html = [html, chunk, unquote(escaped)] append_escaped(rest, text, offset + size + 1, 0, html) end end