Docs tests & a refactor

This commit is contained in:
Max Veytsman
2021-03-06 16:53:46 -05:00
parent 143b0d78c9
commit 682e9d04f3
5 changed files with 73 additions and 28 deletions

View File

@ -8,42 +8,51 @@ defmodule Heroicons do
@doc false @doc false
defmacro __before_compile__(%Macro.Env{module: module}) do defmacro __before_compile__(%Macro.Env{module: module}) do
unless Module.has_attribute?(module, :icon_path) do unless Module.has_attribute?(module, :icon_dir) do
raise CompileError, description: "@icon_path attrubute is required" raise CompileError, description: "@icon_dir attrubute is required"
end end
icon_dir = Module.get_attribute(module, :icon_dir)
icon_paths = icon_paths =
Module.get_attribute(module, :icon_path) Path.absname(icon_dir, :code.priv_dir(:heroicons))
|> Path.join("*.svg") |> Path.join("*.svg")
|> Path.wildcard() |> Path.wildcard()
for path <- icon_paths do for path <- icon_paths do
name = generate_function(path)
Path.basename(path, ".svg") end
|> String.replace("-", "_") end
|> String.to_atom()
quote do @doc false
@doc """ def generate_function(path) do
![](#{unquote(path)}) {: width=24px} name =
Path.basename(path, ".svg")
|> String.replace("-", "_")
|> String.to_atom()
## Examples doc = """
iex> #{unquote(name)}() ![](assets/#{Path.relative_to(path, :code.priv_dir(:heroicons))}) {: width=24px}
iex> #{unquote(name)}(class: "h-6 w-6 text-gray-500")
"""
@spec unquote(name)(keyword(binary)) :: binary
def unquote(name)(opts \\ []) do
icon = File.read!(unquote(path))
{i, _} = :binary.match(icon, ">")
{head, tail} = String.split_at(icon, i) ## Examples
iex> #{name}()
iex> #{name}(class: "h-6 w-6 text-gray-500")
"""
attrs = quote do
opts @doc unquote(doc)
|> Enum.map_join(fn {k, v} -> ~s( #{k}="#{v}") end) @spec unquote(name)(keyword(binary)) :: binary
def unquote(name)(opts \\ []) do
icon = File.read!(unquote(path))
{i, _} = :binary.match(icon, ">")
head <> attrs <> tail {head, tail} = String.split_at(icon, i)
end
attrs =
opts
|> Enum.map_join(fn {k, v} -> ~s( #{k}="#{v}") end)
head <> attrs <> tail
end end
end end
end end

View File

@ -4,6 +4,6 @@ defmodule Heroicons.Outline do
For primary navigation and marketing sections, designed to be rendered at 24x24. For primary navigation and marketing sections, designed to be rendered at 24x24.
""" """
@icon_path "#{:code.priv_dir(:heroicons)}/outline/" @icon_dir "outline/"
@before_compile Heroicons @before_compile Heroicons
end end

View File

@ -5,6 +5,6 @@ defmodule Heroicons.Solid do
For buttons, form elements, and to support text, designed to be rendered at 20x20. For buttons, form elements, and to support text, designed to be rendered at 20x20.
""" """
@icon_path "#{:code.priv_dir(:heroicons)}/solid/" @icon_dir "solid/"
@before_compile Heroicons @before_compile Heroicons
end end

14
mix.exs
View File

@ -7,7 +7,13 @@ defmodule HeroiconsElixir.MixProject do
version: "0.1.0", version: "0.1.0",
elixir: "~> 1.11", elixir: "~> 1.11",
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
deps: deps() deps: deps(),
# Docs
name: "Heroicons Elixir",
source_url: "https://github.com/mveytsman/heroicons_elixir",
description: "Include Heroicons as SVG-strings in your Elixir/Phoenix project!",
docs: docs()
] ]
end end
@ -26,4 +32,10 @@ defmodule HeroiconsElixir.MixProject do
{:ex_doc, "~> 0.23", only: :dev, runtime: false} {:ex_doc, "~> 0.23", only: :dev, runtime: false}
] ]
end end
defp docs do
[
assets: "priv/"
]
end
end end

View File

@ -1,4 +1,28 @@
defmodule HeroiconsTest do defmodule HeroiconsTest do
use ExUnit.Case, async: true use ExUnit.Case, async: true
doctest Heroicons.Solid
@icon """
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path d="M10.394 2.08a1 1 0 00-.788 0l-7 3a1 1 0 000 1.84L5.25 8.051a.999.999 0 01.356-.257l4-1.714a1 1 0 11.788 1.838L7.667 9.088l1.94.831a1 1 0 00.787 0l7-3a1 1 0 000-1.838l-7-3zM3.31 9.397L5 10.12v4.102a8.969 8.969 0 00-1.05-.174 1 1 0 01-.89-.89 11.115 11.115 0 01.25-3.762zM9.3 16.573A9.026 9.026 0 007 14.935v-3.957l1.818.78a3 3 0 002.364 0l5.508-2.361a11.026 11.026 0 01.25 3.762 1 1 0 01-.89.89 8.968 8.968 0 00-5.35 2.524 1 1 0 01-1.4 0zM6 18a1 1 0 001-1v-2.065a8.935 8.935 0 00-2-.712V17a1 1 0 001 1z"/>
</svg>
"""
@tag :tmp_dir
test "generated function", %{tmp_dir: tmp_dir} do
Path.join(tmp_dir, "academic_cap.svg")
|> File.write(@icon)
quote do
defmodule TestIcons do
@icon_dir unquote(Path.absname(tmp_dir))
@before_compile Heroicons
end
end
|> Code.compile_quoted()
assert TestIcons.academic_cap() == @icon
assert TestIcons.academic_cap(class: "h-6 w-6 text-gray-500") =~
~s(class="h-6 w-6 text-gray-500")
end
end end