defmodule ExWeb.Assets do defmacro __using__(opts) do quote do @before_compile unquote(__MODULE__) def init(options) do options end def asset_map do %{} end defoverridable [asset_map: 0] end end defmacro __before_compile__(_env) do module_name = __CALLER__.module root_folder = "assets" [_lang_root_mod, _app_name|folder_modules] = "#{module_name}" |> String.split(".") inner_folder_name = Enum.map(folder_modules, &String.downcase(&1)) |> Path.join folder = Path.join(root_folder, inner_folder_name) quote do require Logger def call(%{path_info: path_info} = conn, _opts) do {:ok, start_folder} = File.cwd folder = Path.join(start_folder, unquote(folder)) Logger.debug "[ExWeb] Assets served from #{folder}" location_of_file = Path.join(path_info) location_of_file = Map.get(asset_map(), location_of_file) || location_of_file file = Path.join(unquote(folder), location_of_file) case File.stat(file) do {:ok, %{type: :regular}} -> Plug.Conn.send_file(conn, 200, file) _ -> ExWeb.Errors.render(conn, 404) end end end end end