defmodule PhoenixAutoDoc.Generator do
def get_info(web_module) do
items_list =
apply(:"#{web_module}.Router", :__routes__, [])
|> Enum.filter(fn i -> not Regex.match?(~r/PhoenixAutoDoc/, "#{i.plug}") end)
|> Enum.group_by(& &1.plug)
|> Map.to_list()
|> Enum.map(fn {module, routes_list} ->
{_, _, _, _, doc, _, functions_list} = Code.fetch_docs(module)
routes_list =
Enum.map(routes_list, fn route ->
route_map = %{
url: route.path,
method: Atom.to_string(route.verb) |> String.upcase(),
function: route.plug_opts
}
Enum.find(functions_list, fn {{_, name, _}, _, _, _, _} ->
name == route.plug_opts
end)
|> case do
{{_, _, _}, _, _, doc, _} ->
Map.merge(route_map, %{
title: documentation_handler(doc) |> title(),
documentation: documentation_handler(doc)
})
nil ->
Map.merge(route_map, %{title: nil, documentation: nil})
end
end)
%{
module: module,
title: documentation_handler(doc) |> title(),
documentation: documentation_handler(doc),
routes: routes_list
}
end)
|> Enum.group_by(& &1.module)
|> Map.to_list()
|> Enum.map(fn {key, [data]} -> {key, data} end)
[{web_module, get_documentation(web_module)}]
|> Enum.concat(items_list)
|> Map.new()
end
defp get_documentation(module_name) do
{_, _, _, _, doc, _, _} = Code.fetch_docs(module_name)
%{
module: module_name,
title: documentation_handler(doc) |> title(),
documentation: documentation_handler(doc),
routes: []
}
end
defp title(str) when is_bitstring(str) do
case Regex.run(~r/^# (.+?)\n/, str) do
[_, title] -> title
_any -> nil
end
end
defp title(_any), do: nil
defp documentation_handler(%{"en" => doc}), do: doc
defp documentation_handler(_any), do: nil
end