Current section

Files

Jump to
heroiconex mix.exs
Raw

mix.exs

defmodule Heroiconex.MixProject do
use Mix.Project
def project do
[
app: :heroiconex,
version: "2.0.19",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
compilers: Mix.compilers ++ [:generate],
deps: deps(),
package: package(),
docs: docs(),
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:phoenix_live_view, "~> 0.20"},
{:floki, "~> 0.34", runtime: false, only: :dev},
{:simplehttp, git: "https://github.com/saleyn/simplehttp.git", runtime: false, only: [:dev, :test]},
#{:simplehttp, "~> 0.5", runtime: false, only: :dev},
{:jason, "~> 1.0", runtime: false, only: [:dev, :test]},
{:ex_doc, ">= 0.0.0", runtime: false, only: :dev}
]
end
defp package do
# These are the default files included in the package
[
name: :heroiconex,
description: "Heroicons component library",
files: ["lib", "config", "mix.exs", "README*"],
maintainers: ["Serge Aleynikov"],
licenses: ["MIT"],
links: %{
"GitHub" => "https://github.com/saleyn/heroiconex",
"Docs" => "https://hex.pm/packages/heroiconex",
}
]
end
defp docs do
[
main: "readme",
extras: ["README.md", "LICENSE"],
]
end
end
defmodule Mix.Tasks.Compile.Generate do
use Mix.Task.Compiler
@url "https://api.github.com/repos/tailwindlabs/heroicons/releases/latest"
@archive "/tmp/heroicons.tgz"
@impl true
def run(args) do
target_files = for s <- ["solid", "outline", "mini"], dst = "lib/#{s}.ex", not File.exists?(dst), do: s
if target_files == [] do
:noop
else
IO.puts("Downloading heroicons")
{:ok, release} = SimpleHttp.get(@url, [ssl: [verify: :verify_none], headers: %{"User-Agent" => "Mozilla"}])
zipurl = Jason.decode!(release.body)["tarball_url"]
vsn = Regex.replace(~r|.*/v([\d\.]+)$|, zipurl, "\\1")
IO.puts("URL: #{zipurl}")
{:ok, %{body: :saved_to_file}} =
SimpleHttp.get(zipurl, [ssl: [verify: :verify_none], headers: %{"User-Agent" => "Mozilla"}, stream: @archive])
{:ok, data} = :erl_tar.extract(@archive |> to_charlist, [:compressed, :memory])
build_files(data)
replace_vsn(vsn)
:lists.member("--preserve", args) || File.rm(@archive)
end
end
defp build_files(data) do
Enum.reduce(data, [], fn {file, svgbin}, acc ->
case Regex.run(~r|[^/]+/optimized/(\d\d)/([^/]+)/(.*)\.svg|, List.to_string(file), [capture: :all_but_first]) do
nil ->
acc
[size, type, filename] ->
s = (size == "20" and type == "solid") && "mini" || type
content = Floki.parse_document!(svgbin) |> Floki.find("path") |> Floki.raw_html
name = Path.basename(filename, ".svg")
[{s, name, content} | acc]
end
end)
|> Enum.reverse
|> Enum.group_by(fn {s, _, _} -> s end, fn {_, name, content} -> {name, content} end)
|> Enum.each(fn {type, icons} ->
dst = "lib/#{type}.ex"
Mix.Generator.copy_template("templates/heroicons.exs", dst, %{type: type, icons: icons}, force: true)
[{_, _}] = Code.compile_file(dst)
end)
end
defp replace_vsn(vsn) do
src_file = File.read!("mix.exs")
[{pos, len}] = Regex.run(~r|\n\s+version: +"([^"]+)",\s*\n.*|, src_file, [capture: :all_but_first, return: :index])
{start, bend} = String.split_at(src_file, pos)
{old_vsn,bend} = String.split_at(bend, len)
if old_vsn != vsn do
IO.puts("Changing version: #{old_vsn} -> #{vsn}")
:ok = File.write("mix.exs", [start, vsn, bend])
end
:ok
end
end