defmodule Mix.Tasks.Compile.Surface do @moduledoc """ Generate CSS and JS/TS assets for components. ## Setup Update `mix.exs`, adding the `:surface` compiler to the list of compilers: ```elixir def project do [ ..., compilers: [:phoenix] ++ Mix.compilers() ++ [:surface] ] end ``` ## Configuration (optional) The Surface compiler provides some options for custom configuration in your `config/dev.exs`. ### Options * `hooks_output_dir` - defines the folder where the compiler generates the JS hooks files. Default is `./assets/js/_hooks/`. * `only_web_namespace` - instructs the compiler to only search for components defined in the project's web module namespace, e.g. `MyAppWeb`. Default is `false`. ### Example config :surface, :compiler, hooks_output_dir: "assets/js/surface" only_web_namespace: true """ use Mix.Task @recursive true alias Mix.Task.Compiler.Diagnostic @switches [ return_errors: :boolean, warnings_as_errors: :boolean ] @doc false def run(args) do {compile_opts, _argv, _err} = OptionParser.parse(args, strict: @switches) Mix.Tasks.Compile.Surface.AssetGenerator.run() |> handle_diagnostics(compile_opts) end @doc false def handle_diagnostics(diagnostics, compile_opts) do case diagnostics do [] -> {:noop, []} diagnostics -> if !compile_opts[:return_errors], do: print_diagnostics(diagnostics) status = status(compile_opts[:warnings_as_errors], diagnostics) {status, diagnostics} end end defp print_diagnostics(diagnostics) do for %Diagnostic{message: message, severity: :warning} <- diagnostics do IO.warn(message, []) end end defp status(warnings_as_errors, diagnostics) do cond do Enum.any?(diagnostics, &(&1.severity == :error)) -> :error warnings_as_errors && Enum.any?(diagnostics, &(&1.severity == :warning)) -> :error true -> :ok end end end