defmodule Oban.Web.Assets do @moduledoc false @behaviour Plug import Plug.Conn @static_path Application.app_dir(:oban_web, ["priv", "static"]) # Icons icon_files = for dir <- ["outline", "solid", "special"], base = Path.join([@static_path, "icons", dir]), file <- File.ls!(base), String.ends_with?(file, ".svg") do path = Path.join(base, file) Module.put_attribute(__MODULE__, :external_resource, path) {Path.join(dir, file), File.read!(path)} end @icons Map.new(icon_files) # Font @external_resource font_path = Path.join(@static_path, "fonts/Inter.woff2") @font File.read!(font_path) # CSS @external_resource css_path = Path.join(@static_path, "app.css") @css File.read!(css_path) # JS phoenix_js_paths = for app <- ~w(phoenix phoenix_html phoenix_live_view)a do path = Application.app_dir(app, ["priv", "static", "#{app}.js"]) Module.put_attribute(__MODULE__, :external_resource, path) path end @external_resource js_path = Path.join(@static_path, "app.js") @js """ #{for path <- phoenix_js_paths, do: path |> File.read!() |> String.replace("//# sourceMappingURL=", "// ")} #{File.read!(js_path)} """ @impl Plug def init(asset), do: asset @impl Plug def call(conn, :css) do serve_asset(conn, @css, "text/css") end def call(conn, :js) do serve_asset(conn, @js, "text/javascript") end def call(conn, :font) do serve_asset(conn, @font, "font/woff2") end def call(conn, :icon) do icon_path = Enum.join(conn.path_params["path"], "/") case Map.get(@icons, icon_path) do nil -> conn |> put_resp_header("content-type", "text/plain") |> send_resp(404, "Icon not found") |> halt() contents -> serve_asset(conn, contents, "image/svg+xml") end end defp serve_asset(conn, contents, content_type) do conn |> put_resp_header("content-type", content_type) |> put_resp_header("cache-control", "public, max-age=31536000, immutable") |> put_private(:plug_skip_csrf_protection, true) |> send_resp(200, contents) |> halt() end for {key, val} <- [css: @css, js: @js] do md5 = Base.encode16(:crypto.hash(:md5, val), case: :lower) def current_hash(unquote(key)), do: unquote(md5) end end