defmodule HtmlEntities do @moduledoc """ Decode HTML entities in a string. ## Examples iex> "Tom & Jerry" |> HtmlEntities.decode "Tom & Jerry" iex> "¡Ay, caramba!" |> HtmlEntities.decode "¡Ay, caramba!" iex> "ő ő" |> HtmlEntities.decode "ő ő" """ @doc "Decode HTML entities in a string." @spec decode(String.t) :: String.t def decode(string) do Regex.replace(~r/\&([^\s]+);/r, string, &replace_entity/2) end html_entities_list_path = Path.join(__DIR__, "html_entities_list.txt") codes = File.stream!(html_entities_list_path) |> Enum.reduce [], fn(line, acc) -> [name, character, codepoint] = :binary.split(line, ",", [:global]) :lists.keystore(name, 1, acc, {name, character, String.rstrip(codepoint)}) end for {name, character, codepoint} <- codes do defp replace_entity(_, unquote(name)), do: unquote(character) defp replace_entity(_, unquote(codepoint)), do: unquote(character) end defp replace_entity(original, "#x" <> code) do try do << String.to_integer(code, 16) :: utf8 >> rescue ArgumentError -> original end end defp replace_entity(original, "#" <> code) do try do << String.to_integer(code) :: utf8 >> rescue ArgumentError -> original end end defp replace_entity(original, _), do: original end