html.ex (2032B)
1 defmodule Plug.HTML do 2 @moduledoc """ 3 Conveniences for generating HTML. 4 """ 5 6 @doc ~S""" 7 Escapes the given HTML to string. 8 9 iex> Plug.HTML.html_escape("foo") 10 "foo" 11 12 iex> Plug.HTML.html_escape("<foo>") 13 "<foo>" 14 15 iex> Plug.HTML.html_escape("quotes: \" & \'") 16 "quotes: " & '" 17 """ 18 @spec html_escape(String.t()) :: String.t() 19 def html_escape(data) when is_binary(data) do 20 IO.iodata_to_binary(to_iodata(data, 0, data, [])) 21 end 22 23 @doc ~S""" 24 Escapes the given HTML to iodata. 25 26 iex> Plug.HTML.html_escape_to_iodata("foo") 27 "foo" 28 29 iex> Plug.HTML.html_escape_to_iodata("<foo>") 30 [[[] | "<"], "foo" | ">"] 31 32 iex> Plug.HTML.html_escape_to_iodata("quotes: \" & \'") 33 [[[[], "quotes: " | """], " " | "&"], " " | "'"] 34 35 """ 36 @spec html_escape_to_iodata(String.t()) :: iodata 37 def html_escape_to_iodata(data) when is_binary(data) do 38 to_iodata(data, 0, data, []) 39 end 40 41 escapes = [ 42 {?<, "<"}, 43 {?>, ">"}, 44 {?&, "&"}, 45 {?", """}, 46 {?', "'"} 47 ] 48 49 for {match, insert} <- escapes do 50 defp to_iodata(<<unquote(match), rest::bits>>, skip, original, acc) do 51 to_iodata(rest, skip + 1, original, [acc | unquote(insert)]) 52 end 53 end 54 55 defp to_iodata(<<_char, rest::bits>>, skip, original, acc) do 56 to_iodata(rest, skip, original, acc, 1) 57 end 58 59 defp to_iodata(<<>>, _skip, _original, acc) do 60 acc 61 end 62 63 for {match, insert} <- escapes do 64 defp to_iodata(<<unquote(match), rest::bits>>, skip, original, acc, len) do 65 part = binary_part(original, skip, len) 66 to_iodata(rest, skip + len + 1, original, [acc, part | unquote(insert)]) 67 end 68 end 69 70 defp to_iodata(<<_char, rest::bits>>, skip, original, acc, len) do 71 to_iodata(rest, skip, original, acc, len + 1) 72 end 73 74 defp to_iodata(<<>>, 0, original, _acc, _len) do 75 original 76 end 77 78 defp to_iodata(<<>>, skip, original, acc, len) do 79 [acc | binary_part(original, skip, len)] 80 end 81 end