lib/gemtext/renderer.ex

defmodule Gemtext.Renderer do
  @moduledoc """
  Gemtext renderer
  """

  require Logger

  @type gemtext_blocks :: Gemtext.Parser.gemtext_blocks()

  @doc ~S'''
  Renders a list of gemtext blocks to string

  ## Examples

      iex> Gemtext.Renderer.render([
      ...> {:h1, "Heading 1"},
      ...> {:text, ""},
      ...> {:text, "This is a robot emoji 🤖"},
      ...> {:text, ""},
      ...> {:link, %{to: "/link"}, nil},
      ...> ])
      "# Heading 1\n\nThis is a robot emoji 🤖\n\n=> /link"
  '''
  def render(items) when is_list(items) do
    items
    |> Enum.map_join("\n", &render_item/1)
  end

  defp render_item({:text, body}), do: body
  defp render_item({:h1, body}), do: "# #{body}"
  defp render_item({:h2, body}), do: "## #{body}"
  defp render_item({:h3, body}), do: "### #{body}"
  defp render_item({:li, body}), do: "* #{body}"
  defp render_item({:quote, body}), do: "> #{body}"
  defp render_item({:link, %{to: to}, nil}), do: "=> #{to}"
  defp render_item({:link, %{to: to}, body}), do: "=> #{to} #{body}"
  defp render_item({:pre, %{title: title}, body}), do: "``` #{title}\n#{body}```"
  defp render_item({:pre, body}), do: "```\n#{body}```"

  @spec render_item(gemtext_blocks()) :: String.t()
  defp render_item(item) do
    Logger.warn("invalid item #{inspect(item)}")
    []
  end
end