defmodule Mix.Tasks.Bootstrap.Generate do @moduledoc """ Generate Font Awesome components. 1. Clone Font Awesome project. $ git clone https://github.com/twbs/icons.git icons-bootstrap 2. Run the task. $ mix bootstrap.generate """ use Mix.Task @shortdoc "Convert source SVG files into HEEX components. Run `git clone https://github.com/twbs/icons.git icons-bootstrap` first." def run(_) do src_path = "./icons-bootstrap/icons/" namespace = "Bootstrap" 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/bootstrap.ex" File.write!(dest_path, file_content) Mix.Task.run("format") 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