defmodule FrancisHtmx do @moduledoc """ Provides a macro to render htmx content by loading htmx.js. Also provides a sigil to render EEx content similar to ~H from Phoenix.LiveView Usage: ```elixir defmodule Example do use Francis import FrancisHtmx htmx(fn _conn -> assigns = %{} ~E\"\"\"
Color Swap Demo
"> Color Swap Demo
\"\"\" end) end ``` In this scenario we are loading serving an HTML that has the htmx.js library loaded and serves the root content given by htmx/1 """ defmacro __using__(opts) do quote do import FrancisHtmx import unquote(__MODULE__), only: [htmx: 1, htmx: 2, sigil_E: 2] checker = ~r/^(\d+\.)?(\d+\.)?(\*|\d+)$/ version = Application.compile_env(:francis_htmx, :version, "2") version = Keyword.get(unquote(opts), :version, version) title = Keyword.get(unquote(opts), :title, "") head = Keyword.get(unquote(opts), :head, "") if !Regex.match?(checker, version) do raise "Invalid version format. Expected format is 'x.y.z' or 'x.y.*'. Got: '#{version}'" end Module.put_attribute(__MODULE__, :htmx_version, version) Module.put_attribute(__MODULE__, :htmx_title, title) Module.put_attribute(__MODULE__, :htmx_head, head) Module.register_attribute(__MODULE__, :htmx_version, accumulate: false) Module.register_attribute(__MODULE__, :htmx_title, accumulate: false) Module.register_attribute(__MODULE__, :htmx_head, accumulate: false) end end @doc """ Renders htmx content by loading htmx.js and rendering binary content. """ @spec htmx((Plug.Conn.t() -> binary())) :: Macro.t() defmacro htmx(content) do quote location: :keep do get("/", fn conn -> html(conn, """ #{@htmx_head}