Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/lazy_html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 16 additions & 16 deletions lib/lazy_html/tree.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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::binary, "<", tag::binary>>
html = [html, ?<, tag]
html = append_attrs(attrs, html)

if tag in @void_tags do
html = <<html::binary, "/>">>
html = [html, "/>"]
to_html(tree, ctx, html)
else
html = <<html::binary, ">">>
html = [html, ?>]
escape_children = tag not in @no_escape_tags
html = to_html(children, %{ctx | escape: escape_children}, html)
html = <<html::binary, "</", tag::binary, ">">>
html = [html, "</", tag, ?>]
to_html(tree, ctx, html)
end
end
Expand All @@ -94,15 +93,16 @@ defmodule LazyHTML.Tree do
end

defp to_html([{:comment, content} | tree], ctx, html) do
to_html(tree, ctx, <<html::binary, "<!--", content::binary, "-->">>)
html = [html, "<!--", content, "-->"]
to_html(tree, ctx, html)
end

defp append_attrs([], html), do: html

defp append_attrs([{name, value} | attrs], html) do
html = <<html::binary, " ", name::binary, ~S/="/>>
html = [html, ?\s, name, ~S/="/]
html = append_escaped(value, html)
html = <<html::binary, ~S/"/>>
html = [html, ?"]
append_attrs(attrs, html)
end

Expand All @@ -116,7 +116,7 @@ defmodule LazyHTML.Tree do

defp append_text(<<_rest::binary>>, text, _whitespace_size, ctx, html)
when not ctx.escape,
do: <<html::binary, text::binary>>
do: [html, text]

defp append_text(<<rest::binary>>, text, whitespace_size, ctx, html)
when ctx.escape,
Expand All @@ -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::binary, text::binary>>
[html, text]
end

defp append_escaped(<<>>, text, offset, size, html) do
chunk = binary_part(text, offset, size)
<<html::binary, chunk::binary>>
[html, chunk]
end

escapes = [
Expand All @@ -160,7 +160,7 @@ defmodule LazyHTML.Tree do
for {char, escaped} <- escapes do
defp append_escaped(<<unquote(char), rest::binary>>, text, offset, size, html) do
chunk = binary_part(text, offset, size)
html = <<html::binary, chunk::binary, unquote(escaped)>>
html = [html, chunk, unquote(escaped)]
append_escaped(rest, text, offset + size + 1, 0, html)
end
end
Expand Down