defmodule Mix.Tasks.Corex.Design do use Mix.Task @shortdoc "Copy Corex design assets into your project" @moduledoc """ Setup Corex design assets into your project. You can select a target directory, defaults to `assets/corex`. You can use the `--force` option to overwrite existing files. ## Examples ```bash mix corex.design mix corex.design assets/design mix corex.design --force mix corex.design --designex ``` ## With Design Tokens You can also generate Tailwind CSS tokens and utilities from design tokens directly in Elixir using Style Dictionary and Token Studio. First install designex, add to your `mix.exs`: ```elixir def deps do [ {:designex, "~> 1.0", only: :dev} ] end ``` Then run the task with the `--designex` option: This will copy the Corex design file including the design tokens and build scripts ```bash mix corex.design --designex ``` Add the configuration for Designex ```elixir config :designex, version: "1.0.2", commit: "1da4b31", cd: Path.expand("../assets", __DIR__), dir: "corex", corex: [ build_args: ~w( --dir=design --script=build.mjs --tokens=tokens ) ] ``` You can now build the design tokens ```bash mix designex corex ``` """ @default_target "assets/corex" @impl Mix.Task def run(args) do Mix.Task.run("app.start") {opts, paths, _} = parse_args(args) target = List.first(paths) || @default_target force = Keyword.get(opts, :force, false) designex = Keyword.get(opts, :designex, false) validate_source!() validate_target!(target, force) maybe_show_designex_info(designex) copy_design_files(target, designex) Mix.shell().info("Corex design copied to: #{target}") end defp parse_args(args) do OptionParser.parse( args, switches: [ force: :boolean, designex: :boolean ] ) end defp validate_source! do source = Application.app_dir(:corex, "priv/design") unless File.exists?(source) do Mix.raise("Corex priv/design directory not found") end end defp validate_target!(target, force) do if File.exists?(target) and not force do Mix.raise(""" #{target} already exists. Re-run with --force to overwrite. """) end end defp maybe_show_designex_info(designex) do if designex and not designex_installed?() do Mix.shell().info(""" To enable token builds, add to mix.exs: {:designex, "~> 1.0", only: :dev} """) end end defp copy_design_files(target, designex) do source = Application.app_dir(:corex, "priv/design") remove_if_exists(target) File.mkdir_p!(target) File.cp_r!(source, target) unless designex do remove_tokens(target) end end defp remove_if_exists(path) do if File.exists?(path) do File.rm_rf!(path) end end defp remove_tokens(target) do tokens_path = Path.join(target, "design") if File.exists?(tokens_path) do File.rm_rf!(tokens_path) end end defp designex_installed? do Code.ensure_loaded?(Designex) end end