defmodule HtmlEntities do @moduledoc """ Decode and encode HTML entities in a string. ## Examples Decoding: iex> "Tom & Jerry" |> HtmlEntities.decode "Tom & Jerry" iex> "¡Ay, caramba!" |> HtmlEntities.decode "¡Ay, caramba!" iex> "ő ő" |> HtmlEntities.decode "ő ő" Encoding: iex> "Tom & Jerry" |> HtmlEntities.encode "Tom & Jerry" iex> "<< KAPOW!! >>" |> HtmlEntities.encode "<< KAPOW!! >>" """ @external_resource "lib/html_entities_list.txt" @doc "Decode HTML entities in a string." @spec decode(String.t) :: String.t def decode(string) do decode(string, "") end defp decode(<<"&", rest::binary>>, acc) do case decode_entity(rest) do {character, rest} -> decode(rest, <>) :error -> decode(rest, <>) end end defp decode(<>, acc) do decode(rest, <>) end defp decode(<<>>, acc) do acc end defp decode_entity(<<"#x", c, rest::binary>>) when c in ?0..?9 do case Integer.parse(<>, 16) do {number, ";" <> rest} -> {<>, rest} _ -> :error end end defp decode_entity(<<"#", rest::binary>>) do case Integer.parse(rest, 10) do {number, ";" <> rest} -> {<>, rest} _ -> :error end end codes = HtmlEntities.Util.load_entities(@external_resource) for {name, character, _codepoint} <- codes do defp decode_entity(<>), do: {unquote(character), rest} end defp decode_entity(_), do: :error @doc "Encode HTML entities in a string." @spec encode(String.t) :: String.t def encode(string) do for <>, into: "" do case x do ?' -> "'" ?" -> """ ?& -> "&" ?< -> "<" ?> -> ">" _ -> <> end end end end