defmodule Mix.Tasks.FontAwesome.Generate do @moduledoc """ Generate Font Awesome components. 1. Clone Font Awesome project. $ git clone https://github.com/FortAwesome/Font-Awesome.git 2. Run the task. $ mix fontawesome.generate """ use Mix.Task @shortdoc "Convert source SVG files into HEEX components. Run `git clone https://github.com/FortAwesome/Font-Awesome.git` first." def run(_) do Enum.each(["brands", "regular", "solid"], &loop_directory/1) Mix.Task.run("format") end defp loop_directory(folder) do src_path = "./Font-Awesome/svgs/#{folder}/" namespace = "FontAwesome.#{String.capitalize(folder)}" file_content = """ defmodule Icons.#{namespace} do @moduledoc \"\"\" Icon name can be the function or passed in as an atom. ### Examples \"\"\" use Phoenix.Component def render(assigns) do apply(__MODULE__, assigns.icon, [assigns]) end """ functions_content = src_path |> File.ls!() |> Enum.filter(&(Path.extname(&1) == ".svg")) |> Enum.map_join("\n\n", &create_component(src_path, &1)) file_content = file_content <> functions_content <> """ end """ dest_path = "./lib/icons/font_awesome/#{folder}.ex" unless File.exists?(dest_path) do File.mkdir_p("./lib/icons/font_awesome") end File.write!(dest_path, file_content) end defp create_component(src_path, filename) do svg_content = File.read!(Path.join(src_path, filename)) |> String.trim() |> String.replace(~r/ Path.basename(".svg") |> String.replace("-", "_") end defp build_component(filename, svg) do """ def #{function_name(filename)}(assigns) do assigns = assigns |> assign_new(:class, fn -> "h-6 w-6" end) |> assign_new(:extra_attributes, fn -> assigns_to_attributes(assigns, [:class]) end) ~H\"\"\" #{svg} \"\"\" end """ end end