Implement mix update script
This commit is contained in:
7
config/config.exs
Normal file
7
config/config.exs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import Config
|
||||||
|
|
||||||
|
config :heroicons,
|
||||||
|
version: "2.0.0",
|
||||||
|
another: [
|
||||||
|
args: ["--version"]
|
||||||
|
]
|
116
lib/heroicons.ex
116
lib/heroicons.ex
@ -16,4 +16,120 @@ defmodule Heroicons do
|
|||||||
|
|
||||||
Heroicons are designed by [Steve Schoger](https://twitter.com/steveschoger)
|
Heroicons are designed by [Steve Schoger](https://twitter.com/steveschoger)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# https://github.com/tailwindlabs/heroicons/releases
|
||||||
|
@latest_version "2.0.0"
|
||||||
|
|
||||||
|
@tmp_dir_name "heroicons-elixir"
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
# Latest known version at the time of publishing.
|
||||||
|
def latest_version, do: @latest_version
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the configured Heroicons version.
|
||||||
|
"""
|
||||||
|
def configured_version do
|
||||||
|
Application.get_env(:heroicons, :version, latest_version())
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def svgs_path, do: Path.join(:code.priv_dir(:heroicons), "icons")
|
||||||
|
|
||||||
|
def icons_path(style), do: Path.join(svgs_path(), style)
|
||||||
|
|
||||||
|
def update do
|
||||||
|
version = configured_version()
|
||||||
|
tmp_dir = Path.join(System.tmp_dir!(), @tmp_dir_name)
|
||||||
|
|
||||||
|
File.rm_rf!(tmp_dir)
|
||||||
|
File.mkdir_p!(tmp_dir)
|
||||||
|
|
||||||
|
url = "https://github.com/tailwindlabs/heroicons/archive/refs/tags/v#{version}.zip"
|
||||||
|
archive = fetch_body!(url)
|
||||||
|
|
||||||
|
case unpack_archive(".zip", archive, tmp_dir) do
|
||||||
|
:ok -> :ok
|
||||||
|
other -> raise "couldn't unpack archive: #{inspect(other)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Copy icon styles, mini, outline and solid, to priv folder
|
||||||
|
Path.join([tmp_dir, "heroicons-#{version}", "optimized"])
|
||||||
|
|> File.ls!()
|
||||||
|
|> Enum.each(fn size ->
|
||||||
|
case size do
|
||||||
|
"20" -> copy_svg_files(size, "solid", "mini")
|
||||||
|
"24" -> Enum.each(File.ls!(), fn style -> copy_svg_files(size, style, style) end)
|
||||||
|
_ -> true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp copy_svg_files(icons_size, src_dir_name, output_dir_name) do
|
||||||
|
tmp_dir = Path.join(System.tmp_dir!(), @tmp_dir_name)
|
||||||
|
svgs_temp_dir = Path.join([tmp_dir, "heroicons-#{configured_version()}", "optimized"])
|
||||||
|
|
||||||
|
File.cp_r!(Path.join([svgs_temp_dir, icons_size, src_dir_name]), icons_path(output_dir_name))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fetch_body!(url) do
|
||||||
|
url = String.to_charlist(url)
|
||||||
|
Logger.debug("Downloading heroicons from #{url}")
|
||||||
|
|
||||||
|
{:ok, _} = Application.ensure_all_started(:inets)
|
||||||
|
{:ok, _} = Application.ensure_all_started(:ssl)
|
||||||
|
|
||||||
|
if proxy = System.get_env("HTTP_PROXY") || System.get_env("http_proxy") do
|
||||||
|
Logger.debug("Using HTTP_PROXY: #{proxy}")
|
||||||
|
%{host: host, port: port} = URI.parse(proxy)
|
||||||
|
:httpc.set_options([{:proxy, {{String.to_charlist(host), port}, []}}])
|
||||||
|
end
|
||||||
|
|
||||||
|
if proxy = System.get_env("HTTPS_PROXY") || System.get_env("https_proxy") do
|
||||||
|
Logger.debug("Using HTTPS_PROXY: #{proxy}")
|
||||||
|
%{host: host, port: port} = URI.parse(proxy)
|
||||||
|
:httpc.set_options([{:https_proxy, {{String.to_charlist(host), port}, []}}])
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/inets
|
||||||
|
cacertfile = CAStore.file_path() |> String.to_charlist()
|
||||||
|
|
||||||
|
http_options = [
|
||||||
|
ssl: [
|
||||||
|
verify: :verify_peer,
|
||||||
|
cacertfile: cacertfile,
|
||||||
|
depth: 2,
|
||||||
|
customize_hostname_check: [
|
||||||
|
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
|
||||||
|
],
|
||||||
|
versions: protocol_versions()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
options = [body_format: :binary]
|
||||||
|
|
||||||
|
case :httpc.request(:get, {url, []}, http_options, options) do
|
||||||
|
{:ok, {{_, 200, _}, _headers, body}} ->
|
||||||
|
body
|
||||||
|
|
||||||
|
other ->
|
||||||
|
raise "couldn't fetch #{url}: #{inspect(other)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp protocol_versions do
|
||||||
|
if otp_version() < 25, do: [:"tlsv1.2"], else: [:"tlsv1.2", :"tlsv1.3"]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp otp_version, do: :erlang.system_info(:otp_release) |> List.to_integer()
|
||||||
|
|
||||||
|
defp unpack_archive(".zip", zip, cwd) do
|
||||||
|
with {:ok, _} <- :zip.unzip(zip, cwd: to_charlist(cwd)), do: :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
defp unpack_archive(_, tar, cwd) do
|
||||||
|
:erl_tar.extract({:binary, tar}, [:compressed, cwd: to_charlist(cwd)])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
29
lib/mix/tasks/heroicons.ex
Normal file
29
lib/mix/tasks/heroicons.ex
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
defmodule Mix.Tasks.Heroicons do
|
||||||
|
@moduledoc """
|
||||||
|
Invokes heroicons mix utilities.
|
||||||
|
Usage:
|
||||||
|
$ mix heroicons
|
||||||
|
"""
|
||||||
|
|
||||||
|
@shortdoc "Invokes heroicons mix utilities"
|
||||||
|
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def run(args) do
|
||||||
|
{_opts, args} = OptionParser.parse!(args, strict: [])
|
||||||
|
|
||||||
|
case args do
|
||||||
|
[] -> help()
|
||||||
|
_ -> Mix.raise("Invalid arguments, expected: mix heroicons")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp help() do
|
||||||
|
Mix.Task.run("app.start")
|
||||||
|
Mix.shell().info("Heroicons v#{Application.spec(:heroicons, :vsn)}")
|
||||||
|
Mix.shell().info("Include Heroicons as SVG-strings in your Elixir/Phoenix project!")
|
||||||
|
Mix.shell().info("\nAvailable tasks:\n")
|
||||||
|
Mix.Tasks.Help.run(["--search", "heroicons."])
|
||||||
|
end
|
||||||
|
end
|
22
lib/mix/tasks/heroicons/update.ex
Normal file
22
lib/mix/tasks/heroicons/update.ex
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
defmodule Mix.Tasks.Heroicons.Update do
|
||||||
|
@moduledoc """
|
||||||
|
Update heroicons.
|
||||||
|
By default, it downloads the latest version but you
|
||||||
|
can configure it in your config files, such as:
|
||||||
|
config :heroicons, :version, "#{Heroicons.latest_version()}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@shortdoc "Update heroicons assets"
|
||||||
|
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def run(args) do
|
||||||
|
{_opts, args} = OptionParser.parse!(args, strict: [])
|
||||||
|
|
||||||
|
case args do
|
||||||
|
[] -> Heroicons.update()
|
||||||
|
_ -> Mix.raise("Invalid arguments, expected: mix heroicons.update")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
6
mix.exs
6
mix.exs
@ -12,7 +12,8 @@ defmodule HeroiconsElixir.MixProject do
|
|||||||
source_url: "https://github.com/mveytsman/heroicons_elixir",
|
source_url: "https://github.com/mveytsman/heroicons_elixir",
|
||||||
description: "Phoenix components for Heroicons!",
|
description: "Phoenix components for Heroicons!",
|
||||||
docs: docs(),
|
docs: docs(),
|
||||||
package: package()
|
package: package(),
|
||||||
|
xref: [exclude: [:httpc, :public_key]]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -29,7 +30,8 @@ defmodule HeroiconsElixir.MixProject do
|
|||||||
{:phoenix_html, "~> 2.14 or ~> 3.0"},
|
{:phoenix_html, "~> 2.14 or ~> 3.0"},
|
||||||
{:phoenix_live_view, ">= 0.16.0", optional: true},
|
{:phoenix_live_view, ">= 0.16.0", optional: true},
|
||||||
{:ex_doc, "~> 0.23", only: :dev, runtime: false},
|
{:ex_doc, "~> 0.23", only: :dev, runtime: false},
|
||||||
{:saxy, "~> 1.4", only: [:dev, :test]}
|
{:saxy, "~> 1.4", only: [:dev, :test]},
|
||||||
|
{:castore, ">= 0.0.0"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
1
mix.lock
1
mix.lock
@ -1,4 +1,5 @@
|
|||||||
%{
|
%{
|
||||||
|
"castore": {:hex, :castore, "0.1.18", "deb5b9ab02400561b6f5708f3e7660fc35ca2d51bfc6a940d2f513f89c2975fc", [:mix], [], "hexpm", "61bbaf6452b782ef80b33cdb45701afbcf0a918a45ebe7e73f1130d661e66a06"},
|
||||||
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
|
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
|
||||||
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
|
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
|
||||||
"floki": {:hex, :floki, "0.30.0", "22ebbe681a5d3777cdd830ca091b1b806d33c3449c26312eadca7f7be685c0c8", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "a9e128a4ca9bb71f11affa315b6768a9ad326d5996ff1e92acf1d7a01a10076a"},
|
"floki": {:hex, :floki, "0.30.0", "22ebbe681a5d3777cdd830ca091b1b806d33c3449c26312eadca7f7be685c0c8", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "a9e128a4ca9bb71f11affa315b6768a9ad326d5996ff1e92acf1d7a01a10076a"},
|
||||||
|
Reference in New Issue
Block a user