defmodule FsBuild do
@external_resource "README.md"
@moduledoc "README.md"
|> File.read!()
|> String.split("<!-- MDOC -->")
|> Enum.fetch!(1)
@doc false
defmacro __using__(opts) do
quote bind_quoted: [opts: opts] do
{from, paths} = FsBuild.__extract__(__MODULE__, opts)
for path <- paths do
@external_resource Path.relative_to_cwd(path)
end
def __mix_recompile__? do
unquote(from) |> Path.wildcard() |> Enum.sort() |> :erlang.md5() !=
unquote(:erlang.md5(paths))
end
end
end
@doc false
def __extract__(module, opts) do
builder = Keyword.fetch!(opts, :build)
from = Keyword.fetch!(opts, :from)
as = Keyword.fetch!(opts, :as)
{adapter_module, adapter_opts} = Keyword.fetch!(opts, :adapter)
:ok = adapter_module.init(adapter_opts)
paths = from |> Path.wildcard() |> Enum.sort()
entries =
Enum.flat_map(paths, fn path ->
content = File.read!(path)
transformed_content = adapter_module.transform(path, content, adapter_opts)
build_entry(builder, path, transformed_content)
end)
Module.put_attribute(module, as, entries)
{from, paths}
end
defp build_entry(builder, path, {_data, _metadata} = transformed_content) do
build_entry(builder, path, [transformed_content])
end
defp build_entry(builder, path, transformed_contents) when is_list(transformed_contents) do
Enum.map(transformed_contents, fn {data, metadata} ->
builder.build(path, data, metadata)
end)
end
end