Skip to content

Commit 350d675

Browse files
committed
Release 0.8.3
1 parent 19b082c commit 350d675

4 files changed

Lines changed: 265 additions & 94 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33

44

5+
## 0.8.3
6+
7+
### Fixed
8+
9+
- `mix igniter.install volt` now fully removes legacy esbuild and tailwind configuration:
10+
- Deletes `config :esbuild` and `config :tailwind` blocks from `config/config.exs` and `config/dev.exs`.
11+
- Removes `esbuild:` and `tailwind:` watchers from the endpoint `watchers` list in `config/dev.exs`.
12+
- Updates mix aliases so `assets.setup`, `assets.build`, and `assets.deploy` no longer reference removed tasks.
13+
14+
### Changed
15+
16+
- Refactored `Mix.Tasks.Volt.Install` for readability: added module aliases, extracted predicate helpers, flattened nested control flow.
17+
18+
19+
520
## 0.8.2
621

722
### Added

lib/mix/tasks/volt.install.ex

Lines changed: 119 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,27 @@ if Code.ensure_loaded?(Igniter) do
1414
This installer will:
1515
1616
1. Remove `:esbuild` and `:tailwind` deps
17-
2. Add Volt build config to `config/config.exs`
18-
3. Add format and lint config to `config/config.exs`
19-
4. Add `Volt.Formatter` plugin to `.formatter.exs`
20-
5. Add `Volt.DevServer` plug to your endpoint
21-
6. Add the Volt watcher to `config/dev.exs`
22-
23-
You may need to manually remove old `config :esbuild` and
24-
`config :tailwind` blocks from `config/config.exs`.
17+
2. Remove `config :esbuild` and `config :tailwind` blocks
18+
3. Update `assets.setup`, `assets.build`, and `assets.deploy` aliases
19+
4. Add Volt build config to `config/config.exs`
20+
5. Add format and lint config to `config/config.exs`
21+
6. Add `Volt.Formatter` plugin to `.formatter.exs`
22+
7. Add `Volt.DevServer` plug to your endpoint
23+
8. Add the Volt watcher to `config/dev.exs`
2524
"""
2625

2726
use Igniter.Mix.Task
2827

28+
alias Igniter.Code.Common
29+
alias Igniter.Code.Function
30+
alias Igniter.Code.Keyword, as: CodeKeyword
31+
alias Igniter.Code.List
32+
alias Igniter.Code.Tuple
33+
alias Igniter.Project.Config, as: ProjectConfig
34+
alias Igniter.Project.Deps, as: ProjectDeps
35+
alias Igniter.Project.Formatter, as: ProjectFormatter
36+
alias Igniter.Project.TaskAliases
37+
2938
@impl Igniter.Mix.Task
3039
def info(_argv, _composing_task) do
3140
%Igniter.Mix.Task.Info{
@@ -37,69 +46,92 @@ if Code.ensure_loaded?(Igniter) do
3746
@impl Igniter.Mix.Task
3847
def igniter(igniter) do
3948
app_name = Igniter.Project.Application.app_name(igniter)
49+
endpoint = endpoint_module(igniter)
4050

4151
igniter
4252
|> remove_old_deps()
43-
|> warn_about_old_config()
53+
|> remove_old_config()
54+
|> remove_old_watchers(app_name, endpoint)
55+
|> update_aliases()
4456
|> add_volt_config()
4557
|> add_format_config()
4658
|> add_lint_config()
4759
|> add_formatter_plugin()
48-
|> add_dev_config(app_name)
60+
|> add_dev_config(app_name, endpoint)
4961
|> add_dev_server_plug()
5062
end
5163

5264
# ── Remove old tooling ──
5365

5466
defp remove_old_deps(igniter) do
5567
igniter
56-
|> Igniter.Project.Deps.remove_dep(:esbuild)
57-
|> Igniter.Project.Deps.remove_dep(:tailwind)
68+
|> ProjectDeps.remove_dep(:esbuild)
69+
|> ProjectDeps.remove_dep(:tailwind)
5870
end
5971

60-
defp warn_about_old_config(igniter) do
61-
has_esbuild =
62-
Igniter.Project.Config.configures_root_key?(igniter, "config.exs", :esbuild)
63-
64-
has_tailwind =
65-
Igniter.Project.Config.configures_root_key?(igniter, "config.exs", :tailwind)
66-
67-
cond do
68-
has_esbuild and has_tailwind ->
69-
Igniter.add_warning(igniter, """
70-
Found `config :esbuild` and `config :tailwind` in config/config.exs.
71-
Please remove them manually — Volt replaces both.
72-
Also remove esbuild/tailwind watchers from config/dev.exs.
73-
""")
74-
75-
has_esbuild ->
76-
Igniter.add_warning(igniter, """
77-
Found `config :esbuild` in config/config.exs.
78-
Please remove it manually — Volt replaces esbuild.
79-
Also remove the esbuild watcher from config/dev.exs.
80-
""")
81-
82-
has_tailwind ->
83-
Igniter.add_warning(igniter, """
84-
Found `config :tailwind` in config/config.exs.
85-
Please remove it manually — Volt replaces the Tailwind CLI.
86-
Also remove the tailwind watcher from config/dev.exs.
87-
""")
88-
89-
true ->
90-
igniter
91-
end
72+
defp remove_old_config(igniter) do
73+
igniter
74+
|> ProjectConfig.remove_application_configuration("config.exs", :esbuild)
75+
|> ProjectConfig.remove_application_configuration("config.exs", :tailwind)
76+
|> ProjectConfig.remove_application_configuration("dev.exs", :esbuild)
77+
|> ProjectConfig.remove_application_configuration("dev.exs", :tailwind)
78+
end
79+
80+
defp remove_old_watchers(igniter, app_name, endpoint) do
81+
Igniter.update_elixir_file(
82+
igniter,
83+
"config/dev.exs",
84+
fn zipper ->
85+
with {:ok, config_zipper} <-
86+
Common.move_to(zipper, &endpoint_config?(&1, app_name, endpoint)),
87+
{:ok, keyword_zipper} <- Function.move_to_nth_argument(config_zipper, 2),
88+
{:ok, watchers_zipper} <- CodeKeyword.get_key(keyword_zipper, :watchers),
89+
{:ok, updated} <- List.remove_from_list(watchers_zipper, &old_watcher?/1) do
90+
{:ok, updated}
91+
else
92+
_ -> {:ok, zipper}
93+
end
94+
end,
95+
required?: false
96+
)
97+
end
98+
99+
defp endpoint_config?(zipper, app_name, endpoint) do
100+
Function.function_call?(zipper, :config, 3) and
101+
Function.argument_equals?(zipper, 0, app_name) and
102+
Function.argument_equals?(zipper, 1, endpoint)
103+
end
104+
105+
defp old_watcher?(item) do
106+
Tuple.elem_equals?(item, 0, :esbuild) or Tuple.elem_equals?(item, 0, :tailwind)
107+
end
108+
109+
defp update_aliases(igniter) do
110+
igniter
111+
|> TaskAliases.modify_existing_alias(:"assets.setup", &replace_with_empty/1)
112+
|> TaskAliases.modify_existing_alias(:"assets.build", &replace_with_build/1)
113+
|> TaskAliases.modify_existing_alias(:"assets.deploy", &replace_with_deploy/1)
114+
end
115+
116+
defp replace_with_empty(zipper), do: {:ok, Common.replace_code(zipper, [])}
117+
118+
defp replace_with_build(zipper) do
119+
{:ok, Common.replace_code(zipper, ["compile", "volt.build --tailwind"])}
120+
end
121+
122+
defp replace_with_deploy(zipper) do
123+
{:ok, Common.replace_code(zipper, ["volt.build --tailwind", "phx.digest"])}
92124
end
93125

94126
# ── Add Volt config ──
95127

96128
defp add_volt_config(igniter) do
97129
igniter
98-
|> Igniter.Project.Config.configure("config.exs", :volt, [:entry], "assets/js/app.ts")
99-
|> Igniter.Project.Config.configure("config.exs", :volt, [:outdir], "priv/static/assets")
100-
|> Igniter.Project.Config.configure("config.exs", :volt, [:target], :es2020)
101-
|> Igniter.Project.Config.configure("config.exs", :volt, [:sourcemap], :hidden)
102-
|> Igniter.Project.Config.configure(
130+
|> ProjectConfig.configure("config.exs", :volt, [:entry], "assets/js/app.ts")
131+
|> ProjectConfig.configure("config.exs", :volt, [:outdir], "priv/static/assets")
132+
|> ProjectConfig.configure("config.exs", :volt, [:target], :es2020)
133+
|> ProjectConfig.configure("config.exs", :volt, [:sourcemap], :hidden)
134+
|> ProjectConfig.configure(
103135
"config.exs",
104136
:volt,
105137
[:tailwind],
@@ -133,7 +165,7 @@ if Code.ensure_loaded?(Igniter) do
133165

134166
code = Enum.map_join(format_kw, ",\n ", fn {k, v} -> "#{k}: #{inspect(v)}" end)
135167

136-
Igniter.Project.Config.configure(
168+
ProjectConfig.configure(
137169
igniter,
138170
"config.exs",
139171
:volt,
@@ -143,7 +175,7 @@ if Code.ensure_loaded?(Igniter) do
143175
end
144176

145177
defp add_lint_config(igniter) do
146-
Igniter.Project.Config.configure(
178+
ProjectConfig.configure(
147179
igniter,
148180
"config.exs",
149181
:volt,
@@ -162,29 +194,20 @@ if Code.ensure_loaded?(Igniter) do
162194
end
163195

164196
defp add_formatter_plugin(igniter) do
165-
Igniter.Project.Formatter.add_formatter_plugin(igniter, Volt.Formatter)
197+
ProjectFormatter.add_formatter_plugin(igniter, Volt.Formatter)
166198
end
167199

168-
defp add_dev_config(igniter, app_name) do
169-
endpoint = endpoint_module(igniter)
170-
171-
Igniter.Project.Config.configure(
172-
igniter,
173-
"dev.exs",
174-
app_name,
175-
[endpoint, :watchers, :volt],
200+
defp add_dev_config(igniter, app_name, endpoint) do
201+
watcher =
176202
{:code,
177203
Sourceror.parse_string!("""
178204
{Mix.Tasks.Volt.Dev, :run, [~w(--tailwind)]}
179205
""")}
180-
)
181-
|> Igniter.Project.Config.configure(
182-
"dev.exs",
183-
:volt,
184-
[:server, :prefix],
185-
"/assets"
186-
)
187-
|> Igniter.Project.Config.configure(
206+
207+
igniter
208+
|> ProjectConfig.configure("dev.exs", app_name, [endpoint, :watchers, :volt], watcher)
209+
|> ProjectConfig.configure("dev.exs", :volt, [:server, :prefix], "/assets")
210+
|> ProjectConfig.configure(
188211
"dev.exs",
189212
:volt,
190213
[:server, :watch_dirs],
@@ -218,53 +241,56 @@ if Code.ensure_loaded?(Igniter) do
218241
end
219242

220243
defp insert_dev_server_plug(zipper, endpoint) do
221-
with :error <-
222-
Igniter.Code.Common.move_to(zipper, fn z ->
223-
Igniter.Code.Function.function_call?(z, :plug) and
224-
Igniter.Code.Function.argument_equals?(z, 0, Volt.DevServer)
225-
end),
226-
{:ok, zipper} <- Igniter.Code.Common.move_to(zipper, &code_reloading?/1) do
244+
with :error <- Common.move_to(zipper, &has_dev_server_plug?/1),
245+
{:ok, zipper} <- Common.move_to(zipper, &code_reloading?/1) do
227246
{:ok,
228-
Igniter.Code.Common.add_code(
247+
Common.add_code(
229248
zipper,
230249
"""
231250
plug Volt.DevServer, root: "assets"
232251
""",
233252
placement: :after
234253
)}
235254
else
236-
{:ok, _} ->
237-
{:ok, zipper}
255+
{:ok, _} -> {:ok, zipper}
256+
:error -> dev_server_warning(endpoint)
257+
end
258+
end
238259

239-
:error ->
240-
{:warning,
241-
"""
242-
Could not find the code_reloading? section in `#{inspect(endpoint)}`.
243-
Please add the plug manually inside `if code_reloading? do`:
260+
defp has_dev_server_plug?(zipper) do
261+
Function.function_call?(zipper, :plug) and
262+
Function.argument_equals?(zipper, 0, Volt.DevServer)
263+
end
244264

245-
plug Volt.DevServer, root: "assets"
246-
"""}
247-
end
265+
defp dev_server_warning(endpoint) do
266+
{:warning,
267+
"""
268+
Could not find the code_reloading? section in `#{inspect(endpoint)}`.
269+
Please add the plug manually inside `if code_reloading? do`:
270+
271+
plug Volt.DevServer, root: "assets"
272+
"""}
248273
end
249274

250275
# ── Helpers ──
251276

252277
defp code_reloading?(zipper) do
253-
Igniter.Code.Function.function_call?(zipper, :if, 2) &&
254-
Igniter.Code.Function.argument_matches_predicate?(
278+
Function.function_call?(zipper, :if, 2) &&
279+
Function.argument_matches_predicate?(
255280
zipper,
256281
0,
257-
&Igniter.Code.Common.variable?(&1, :code_reloading?)
282+
&Common.variable?(&1, :code_reloading?)
258283
)
259284
end
260285

261286
defp endpoint_module(igniter) do
262-
app_name = Igniter.Project.Application.app_name(igniter)
287+
app_name =
288+
igniter
289+
|> Igniter.Project.Application.app_name()
290+
|> to_string()
291+
|> Macro.camelize()
263292

264-
app_name
265-
|> to_string()
266-
|> Macro.camelize()
267-
|> then(&Module.concat([String.to_atom("#{&1}Web"), Endpoint]))
293+
Module.concat([String.to_atom("#{app_name}Web"), Endpoint])
268294
end
269295
end
270296
else

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule Volt.MixProject do
22
use Mix.Project
33

4-
@version "0.8.2"
4+
@version "0.8.3"
55
@source_url "https://github.com/elixir-volt/volt"
66

77
def project do

0 commit comments

Comments
 (0)