   * `data`: Contents of the page fragment
   """
 
+  alias Serum.HtmlTreeHelper, as: Html
   alias Serum.Plugin
 
   @type t :: %__MODULE__{

  @doc "Creates a new `Fragment` struct."
  @spec new(binary() | nil, binary(), map(), binary()) :: Result.t(t())
  def new(file, output, metadata, data) do
    case Plugin.rendering_fragment(Floki.parse(data), metadata) do
      {:ok, html_tree} ->
        images =
          html_tree
          |> Floki.find("img")
          |> Enum.map(fn {"img", attrs, _} -> Map.new(attrs)["src"] || [] end)
          |> List.flatten()

        fragment = %__MODULE__{
          file: file,
          output: output,
          metadata: Map.put(metadata, :images, images),
          data: Floki.raw_html(html_tree)
        }


    end
  end

  @spec set_header_ids(Html.tree(), map()) :: {Html.tree(), map()}
  defp set_header_ids(tree, state)

  defp set_header_ids({<<?h, ch::8>>, _, _} = tree, state) when ch in ?1..?6 do
    {tag_name, attrs, children} = tree

    case Enum.find(attrs, fn {k, _} -> k === "id" end) do
      {"id", id} ->
        {tree, increase_count(state, id)}

      nil ->
        id = generate_id(tree)

        new_tree =
          case state[id] do
            nil -> {tag_name, [{"id", id} | attrs], children}
            x -> {tag_name, [{"id", "#{id}-#{x + 1}"} | attrs], children}
          end

        {new_tree, increase_count(state, id)}
    end
  end

  defp set_header_ids(tree, state), do: {tree, state}

  @spec generate_id(Html.tree()) :: binary()
  defp generate_id(tree) do
    tree
    |> Floki.text()
    |> String.downcase()
    |> String.replace(~r/\s/, "-")
  end

  @spec increase_count(map(), binary()) :: map()
  defp increase_count(map, id), do: Map.update(map, id, 1, &(&1 + 1))

  @spec extract_images(Html.tree()) :: [binary()]
  defp extract_images(tree) do
    tree
    |> Floki.find("img")
    |> Enum.map(fn {"img", attrs, _} ->
      attrs |> Enum.find(fn {k, _} -> k === "src" end) |> elem(1)
    end)
    |> List.flatten()
  end

  defprotocol Source do
    alias Serum.Result

