From a8a82b72491a34353e3700e15f873cb0414f5bd9 Mon Sep 17 00:00:00 2001 From: Roman Kurakin Date: Thu, 10 Sep 2026 05:53:32 +0500 Subject: [PATCH] fix(js): read the format key only when it holds formatter options `Volt.Builder` reads `config :volt, :format` as the bundle format, where the value is an atom such as `:esm`. `Volt.JS.Format` and `Volt.JS.Helpers` read the same key as formatter options and expect a keyword list. A project that asks the bundler for ESM therefore cannot use `Volt.Formatter` or `mix volt.js.check`. `load_config/0` raises a `CaseClauseError`, and `discovery_config/1` passes the atom on to `Keyword.get/3`. Both now accept a keyword list and fall back otherwise. A configuration that worked before still works. A value that raised before now falls back to the JSON configuration. --- lib/volt/js/format.ex | 11 ++++++++--- lib/volt/js/helpers.ex | 8 +++++++- test/volt/js/format_test.exs | 6 ++++++ test/volt/js/helpers_test.exs | 13 +++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/volt/js/format.ex b/lib/volt/js/format.ex index 9743f34..0df0bb9 100644 --- a/lib/volt/js/format.ex +++ b/lib/volt/js/format.ex @@ -27,9 +27,14 @@ defmodule Volt.JS.Format do @discovery_keys ~w(root sources ignore)a def load_config do - case Application.get_env(:volt, :format) do - nil -> load_json_config() - opts when is_list(opts) -> Keyword.drop(opts, @discovery_keys) + opts = Application.get_env(:volt, :format) + + # The bundler reads the same key, where the value is an atom such as :esm. + # Only a keyword list carries formatter options. + if Keyword.keyword?(opts) do + Keyword.drop(opts, @discovery_keys) + else + load_json_config() end end diff --git a/lib/volt/js/helpers.ex b/lib/volt/js/helpers.ex index a092c94..8c6a5d4 100644 --- a/lib/volt/js/helpers.ex +++ b/lib/volt/js/helpers.ex @@ -38,5 +38,11 @@ defmodule Volt.JS.Helpers do end defp discovery_config(nil), do: [] - defp discovery_config(tool), do: Application.get_env(:volt, tool, []) + + defp discovery_config(tool) do + config = Application.get_env(:volt, tool, []) + + # The bundler reads :format as an atom, so it holds no discovery keys. + if Keyword.keyword?(config), do: config, else: [] + end end diff --git a/test/volt/js/format_test.exs b/test/volt/js/format_test.exs index 2cb7794..bc68de7 100644 --- a/test/volt/js/format_test.exs +++ b/test/volt/js/format_test.exs @@ -25,4 +25,10 @@ defmodule Volt.JS.FormatTest do assert Format.load_config() == [semi: false, print_width: 100] end + + test "load_config/0 ignores a bundle format set on the same key" do + Application.put_env(:volt, :format, :esm) + + assert Format.load_config() == Format.load_json_config() + end end diff --git a/test/volt/js/helpers_test.exs b/test/volt/js/helpers_test.exs index 8eea207..9e1c764 100644 --- a/test/volt/js/helpers_test.exs +++ b/test/volt/js/helpers_test.exs @@ -44,6 +44,19 @@ defmodule Volt.JS.HelpersTest do assert Helpers.discover_files(tool: :lint) == [Path.join(tmp_dir, "lint/source.ts")] end + test "a bundle format on the same key holds no discovery options", %{tmp_dir: tmp_dir} do + Application.put_env(:volt, :format, :esm) + + Application.put_env(:volt, :lint, + root: tmp_dir, + sources: ["lint/**/*.ts"], + ignore: [] + ) + + assert Helpers.discover_format_files() == [] + assert Helpers.discover_files(tool: :lint) == [Path.join(tmp_dir, "lint/source.ts")] + end + defp restore_env(key, nil), do: Application.delete_env(:volt, key) defp restore_env(key, value), do: Application.put_env(:volt, key, value) end