Current section
Files
Jump to
Current section
Files
lib/mix/tasks/phoenix_iconify.ex
defmodule Mix.Tasks.PhoenixIconify do
@shortdoc "Manage PhoenixIconify icons and cache"
@moduledoc """
Tasks for managing PhoenixIconify icons and cache.
## Commands
mix phoenix_iconify # Show help
mix phoenix_iconify.stats # Show icon and cache statistics
mix phoenix_iconify.list # List all icons in manifest
mix phoenix_iconify.cache # Cache management
mix phoenix_iconify.prefetch # Scan and fetch discovered icons
mix phoenix_iconify.audit # Report missing discovered icons
mix phoenix_iconify.clean # Remove unused manifest icons
"""
use Mix.Task
@impl true
def run(_args) do
Mix.shell().info("""
PhoenixIconify - Iconify icons for Phoenix
Available commands:
mix phoenix_iconify.stats Show icon and cache statistics
mix phoenix_iconify.list List all icons in manifest
mix phoenix_iconify.cache Cache management (fetch, clear, list)
mix phoenix_iconify.prefetch Scan and fetch discovered icons
mix phoenix_iconify.audit Report missing discovered icons
mix phoenix_iconify.clean Remove unused manifest icons
For more info on a command:
mix help phoenix_iconify.<command>
""")
end
end
defmodule Mix.Tasks.PhoenixIconify.Stats do
@shortdoc "Show icon and cache statistics"
@moduledoc """
Shows statistics about discovered icons and cached icon sets.
mix phoenix_iconify.stats
"""
use Mix.Task
@impl true
def run(_args) do
Application.ensure_all_started(:phoenix_iconify)
manifest = PhoenixIconify.Manifest.read()
cache_stats = PhoenixIconify.Cache.stats()
prefixes =
manifest
|> Enum.map(fn {name, _icon} -> prefix_from_icon(name) || "unknown" end)
|> Enum.frequencies()
|> Enum.sort_by(fn {_, count} -> -count end)
Mix.shell().info("""
PhoenixIconify Statistics
========================
Manifest:
Total icons: #{map_size(manifest)}
By prefix:
#{format_prefixes(prefixes)}
Cache:
Cached sets: #{cache_stats.sets}
Total size: #{cache_stats.total_size_human}
""")
end
defp format_prefixes(prefixes) do
prefixes
|> Enum.map(fn {prefix, count} -> [" - ", prefix, ": ", Integer.to_string(count)] end)
|> Enum.intersperse("\n")
|> IO.iodata_to_binary()
end
defp prefix_from_icon(name) do
case String.split(name, ":", parts: 2) do
[prefix, _] -> prefix
_ -> nil
end
end
end
defmodule Mix.Tasks.PhoenixIconify.List do
@shortdoc "List all icons in manifest"
@moduledoc """
Lists all icons currently in the manifest.
mix phoenix_iconify.list
mix phoenix_iconify.list --prefix heroicons
## Options
* `--prefix` - Filter by icon prefix
"""
use Mix.Task
@impl true
def run(args) do
Application.ensure_all_started(:phoenix_iconify)
{opts, _, _} = OptionParser.parse(args, strict: [prefix: :string])
prefix_filter = opts[:prefix]
icons =
PhoenixIconify.Manifest.read()
|> Map.keys()
|> Enum.sort()
|> maybe_filter_prefix(prefix_filter)
if icons == [] do
Mix.shell().info("No icons found in manifest.")
else
Mix.shell().info("\nIcons in manifest (#{length(icons)}):\n")
Enum.each(icons, fn name ->
Mix.shell().info(" #{name}")
end)
Mix.shell().info("")
end
end
defp maybe_filter_prefix(icons, nil), do: icons
defp maybe_filter_prefix(icons, prefix) do
Enum.filter(icons, &String.starts_with?(&1, "#{prefix}:"))
end
end
defmodule Mix.Tasks.PhoenixIconify.Cache do
@shortdoc "Manage icon set cache"
@moduledoc """
Manage the local icon set cache.
mix phoenix_iconify.cache list # List cached icon sets
mix phoenix_iconify.cache fetch # Fetch icon sets for all manifest icons
mix phoenix_iconify.cache clear # Clear the cache
## Fetch
Pre-fetches complete icon sets for all prefixes used in your manifest.
This speeds up future compilations.
mix phoenix_iconify.cache fetch
mix phoenix_iconify.cache fetch heroicons lucide
## Clear
Removes all cached icon sets.
mix phoenix_iconify.cache clear
"""
use Mix.Task
@impl true
def run(["list" | _]) do
sets = PhoenixIconify.Cache.list_cached_sets()
if sets == [] do
Mix.shell().info("No icon sets cached.")
else
Mix.shell().info("\nCached icon sets (#{length(sets)}):\n")
Enum.each(sets, &Mix.shell().info(" #{&1}"))
Mix.shell().info("")
stats = PhoenixIconify.Cache.stats()
Mix.shell().info("Total size: #{stats.total_size_human}")
end
end
def run(["fetch" | prefixes]) do
{:ok, _} = Application.ensure_all_started(:req)
prefixes_to_fetch = prefixes_to_fetch(prefixes)
if prefixes_to_fetch == [] do
Mix.shell().info("No prefixes to fetch. Run 'mix compile' first to discover icons.")
else
Mix.shell().info("Fetching #{length(prefixes_to_fetch)} icon set(s)...")
Enum.each(prefixes_to_fetch, &fetch_prefix/1)
end
end
def run(["clear" | _]) do
PhoenixIconify.Cache.clear()
Mix.shell().info("Cache cleared.")
end
def run(_) do
Mix.shell().info("""
Usage:
mix phoenix_iconify.cache list List cached icon sets
mix phoenix_iconify.cache fetch Fetch icon sets
mix phoenix_iconify.cache clear Clear the cache
""")
end
defp prefixes_to_fetch([]) do
PhoenixIconify.Manifest.read()
|> Enum.map(fn {name, _icon} -> prefix_from_icon(name) end)
|> Enum.reject(&is_nil/1)
|> Enum.uniq()
end
defp prefixes_to_fetch(prefixes), do: prefixes
defp prefix_from_icon(name) do
case String.split(name, ":", parts: 2) do
[prefix, _] -> prefix
_ -> nil
end
end
defp fetch_prefix(prefix) do
if PhoenixIconify.Cache.has_set?(prefix) do
Mix.shell().info(" #{prefix}: already cached")
else
report_prefix_fetch(prefix, PhoenixIconify.Cache.fetch_set(prefix))
end
end
defp report_prefix_fetch(prefix, {:ok, set}) do
Mix.shell().info(" #{prefix}: fetched (#{Iconify.Set.count(set)} icons)")
end
defp report_prefix_fetch(prefix, {:error, reason}) do
Mix.shell().error(" #{prefix}: failed (#{inspect(reason)})")
end
end
defmodule Mix.Tasks.PhoenixIconify.Prefetch do
@shortdoc "Scan and fetch discovered icons"
@moduledoc """
Scans the project for icon component usage and updates the manifest.
mix phoenix_iconify.prefetch
"""
use Mix.Task
@impl true
def run(_args) do
Mix.Task.run("compile.phoenix_iconify")
end
end
defmodule Mix.Tasks.PhoenixIconify.Audit do
@shortdoc "Report missing discovered icons"
@moduledoc """
Reports discovered icons that are not present in the manifest.
mix phoenix_iconify.audit
"""
use Mix.Task
@impl true
def run(_args) do
manifest = PhoenixIconify.Manifest.read()
missing = Enum.reject(PhoenixIconify.Discovery.icons(), &Map.has_key?(manifest, &1))
if missing == [] do
Mix.shell().info("PhoenixIconify: all discovered icons are present in the manifest.")
else
Mix.shell().error("PhoenixIconify: #{length(missing)} missing icon(s):")
Enum.each(missing, &Mix.shell().error(" #{&1}"))
end
end
end
defmodule Mix.Tasks.PhoenixIconify.Clean do
@shortdoc "Remove unused manifest icons"
@moduledoc """
Removes manifest entries that are not currently discovered or configured as extra icons.
mix phoenix_iconify.clean
"""
use Mix.Task
@impl true
def run(_args) do
keep = MapSet.new(PhoenixIconify.Discovery.icons())
manifest = PhoenixIconify.Manifest.read()
cleaned = Map.take(manifest, MapSet.to_list(keep))
removed = map_size(manifest) - map_size(cleaned)
PhoenixIconify.Manifest.write(cleaned)
PhoenixIconify.Manifest.clear_cache()
Mix.shell().info("PhoenixIconify: removed #{removed} unused icon(s).")
end
end