Files
phosphoricons/lib/heroicons/generator.ex
2022-09-02 18:57:26 -04:00

104 lines
2.4 KiB
Elixir

defmodule Heroicons.Generator do
@moduledoc false
defmacro __using__(icon_dir: icon_dir) do
icon_paths =
Path.absname(icon_dir, :code.priv_dir(:heroicons))
|> Path.join("*.svg")
|> Path.wildcard()
require Phoenix.Component
for path <- icon_paths do
relative_path = Path.relative_to(path, :code.priv_dir(:heroicons))
generate(relative_path)
end
end
@doc false
def generate(path) do
name = Heroicons.Generator.name(path)
quote do
@doc Heroicons.Generator.doc(unquote(name), unquote(path))
def unquote(name)(assigns_or_opts \\ [])
def unquote(name)(assigns) when is_map(assigns) do
Heroicons.Generator.icon_component(unquote(path), assigns)
end
def unquote(name)(opts) when is_list(opts) do
Heroicons.Generator.icon_function(unquote(path), opts)
end
end
end
@doc false
def name(path) do
Path.basename(path, ".svg")
|> String.replace("-", "_")
|> String.to_atom()
end
@doc false
def doc(name, path) do
"""
![](assets/#{path}) {: width=24px}
## Examples
Use as a `Phoenix.Component`
<.#{name} />
<.#{name} class="w-6 h-6 text-gray-500" />
or as a function
<%= #{name}() %>
<%= #{name}(class: "h-6 w-6 text-gray-500") %>
"""
end
if function_exported?(Phoenix.Component, :assigns_to_attributes, 2) do
@assign_mod Phoenix.Component
@assigns_to_attrs_mod Phoenix.Component
else
@assign_mod Phoenix.LiveView
@assigns_to_attrs_mod Phoenix.LiveView.Helpers
end
@doc false
def icon_component(path, assigns) when is_map(assigns) do
attrs = @assigns_to_attrs_mod.assigns_to_attributes(assigns)
assigns = @assign_mod.assign(assigns, :attrs, attrs)
{component, _binding} =
Code.eval_quoted(
Heroicons.Cache.fetch_component(path),
assigns: assigns
)
component
end
@doc false
def icon_function(path, opts) when is_list(opts) do
attrs =
for {k, v} <- opts do
safe_k =
k |> Atom.to_string() |> String.replace("_", "-") |> Phoenix.HTML.Safe.to_iodata()
safe_v = v |> Phoenix.HTML.Safe.to_iodata()
{:safe, [?\s, safe_k, ?=, ?", safe_v, ?"]}
end
{:safe,
[
"<svg",
Phoenix.HTML.Safe.to_iodata(attrs),
" ",
Heroicons.Cache.fetch_body(path)
]}
end
end