defmodule Markdown do @doc """ Parses a given string with Markdown syntax and returns the associated HTML for that string. ## Examples iex> Markdown.parse("This is a paragraph") "

This is a paragraph

" iex> Markdown.parse("#Header!\n* __Bold Item__\n* _Italic Item_") "

Header!

" """ @spec parse(String.t()) :: String.t() def parse(m) do patch(Enum.join(Enum.map(String.split(m, "\n"), fn t -> process(t) end))) end defp process(t) do if String.starts_with?(t, "#") || String.starts_with?(t, "*") do if String.starts_with?(t, "#") do enclose_with_header_tag(parse_header_md_level(t)) else parse_list_md_level(t) end else enclose_with_paragraph_tag(String.split(t)) end end defp parse_header_md_level(hwt) do [h | t] = String.split(hwt) {to_string(String.length(h)), Enum.join(t, " ")} end defp parse_list_md_level(l) do t = String.split(String.trim_leading(l, "* ")) "
  • " <> join_words_with_tags(t) <> "
  • " end defp enclose_with_header_tag({hl, htl}) do " hl <> ">" <> htl <> " hl <> ">" end defp enclose_with_paragraph_tag(t) do "

    #{join_words_with_tags(t)}

    " end defp join_words_with_tags(t) do Enum.join(Enum.map(t, fn w -> replace_md_with_tag(w) end), " ") end defp replace_md_with_tag(w) do replace_suffix_md(replace_prefix_md(w)) end defp replace_prefix_md(w) do cond do w =~ ~r/^#{"__"}{1}/ -> String.replace(w, ~r/^#{"__"}{1}/, "", global: false) w =~ ~r/^[#{"_"}{1}][^#{"_"}+]/ -> String.replace(w, ~r/_/, "", global: false) true -> w end end defp replace_suffix_md(w) do cond do w =~ ~r/#{"__"}{1}$/ -> String.replace(w, ~r/#{"__"}{1}$/, "") w =~ ~r/[^#{"_"}{1}]/ -> String.replace(w, ~r/_/, "") true -> w end end defp patch(l) do String.replace_suffix( String.replace(l, "
  • ", "" ) end end