   Floki). It is recommended to implement this callback if you want to modify
   the HTML document without worrying about breaking it.
   """
-  @callback rendering_fragment(html :: Floki.html_tree(), metadata :: map()) ::
-              Result.t(Floki.html_tree())
+  defcallback rendering_fragment(html :: Floki.html_tree(), metadata :: map()) ::
+                Result.t(Floki.html_tree())
 
   @doc """
   Called after producing a HTML fragment for each page.
 
   Plugins can modify the contents and metadata of each fragment here.
   """
-  @callback rendered_fragment(frag :: Fragment.t()) :: Result.t(Fragment.t())
+  defcallback rendered_fragment(frag :: Fragment.t()) :: Result.t(Fragment.t())
 
   @doc """
   Called when Serum has rendered a full page and it's about to write to an


  Plugins can alter the raw contents of the page to be written.
  """
  @callback rendered_page(file :: File.t()) :: Result.t(File.t())

  @doc """
  Called after writing each output to a file.
  """
  @callback wrote_file(file :: File.t()) :: Result.t()

  @doc """
  Called if the whole build process has finished successfully.
  """
  @callback build_succeeded(src :: binary(), dest :: binary()) :: Result.t()

  @doc """
  Called if the build process has failed for some reason.
  """
  @callback build_failed(src :: binary(), dest :: binary(), result :: Result.t() | Result.t(term)) ::
              Result.t()

  @doc """
  Called right before Serum exits, whether the build has succeeded or not.

  Plugins can manipulate the list of files to be read and pass it to
  the next plugin.
  """
  defcallback reading_posts(files :: [binary()]) :: Result.t([binary()])

  @doc """
  Called before reading input files.
