Last active
December 20, 2024 13:19
-
-
Save Fudoshiki/014d730f27e44916f92a28b69e777d2f to your computer and use it in GitHub Desktop.
recompile exception
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PhoenixAssetPipeline.Helpers do | |
@moduledoc false | |
import PhoenixAssetPipeline.Obfuscator | |
defmacro __before_compile__(env) do | |
classes = Module.get_attribute(env.module, :__classes__, []) | |
recompile? = Enum.any?(classes, &match?({:error, _}, &1)) | |
quote do | |
def __mix_recompile__?, do: unquote(recompile?) | |
def __verify_classes__(_) do | |
unquote(__MODULE__).__verify_classes__(unquote(classes), unquote(Macro.escape(env))) | |
end | |
end | |
end | |
defmacro __using__(_) do | |
quote do | |
import unquote(__MODULE__) | |
Module.register_attribute(__MODULE__, :__classes__, accumulate: true) | |
@after_verify {__MODULE__, :__verify_classes__} | |
@before_compile unquote(__MODULE__) | |
end | |
end | |
defmacro class(class_name) do | |
class_name | |
|> obfuscate() | |
|> Enum.map(fn | |
{:ok, {_, short_name} = class} -> | |
Module.put_attribute(__CALLER__.module, :__classes__, {:ok, class}) | |
short_name | |
{:error, class} -> | |
Module.put_attribute(__CALLER__.module, :__classes__, {:error, class}) | |
nil | |
end) | |
|> Enum.sort() | |
end | |
defp obfuscate([_ | _] = class_names) do | |
for class_name <- class_names do | |
case obfuscate_class(class_name) do | |
{:ok, short_name} -> {:ok, short_name} | |
{:error, class_name} -> {:error, class_name} | |
end | |
end | |
end | |
defp obfuscate(class_name), do: obfuscate([class_name]) | |
def __verify_classes__(classes, env) do | |
for {:error, {class_name, _}} <- classes do | |
IO.warn("Invalid class name: #{class_name}", Macro.Env.stacktrace(env)) | |
end | |
:ok | |
end | |
end | |
defmodule PhoenixAssetPipeline.Obfuscator do | |
@moduledoc false | |
@pattern ~r/(?:(?<prefix>(?:[a-z0-9\[\]&:\(\)\.\-]+:)+))?(?<class>(?!(?:\d+)$)(?:[a-zA-Z_][a-zA-Z0-9_-]*|\[[^\]]*\]))/iu | |
def obfuscate_class(class_name) when is_binary(class_name) do | |
if Regex.match?(~r/^#{@pattern.source}$/, class_name), | |
do: {:ok, {class_name, minify(class_name)}}, | |
else: {:error, {class_name, nil}} | |
end | |
def obfuscate_class(class_name), do: {:error, {class_name, nil}} | |
def obfuscate_css(_) do | |
"" | |
end | |
def obfuscate_js(_) do | |
"" | |
end | |
defp minify(class_name), do: String.first(class_name) | |
end |
Runtime (works, as expected)
mix phx.server
- Write an incorrect class
<body class={class(["bg-wh ite", "dark:bg-gray-900"])}>
and it will raise an error in runtime (as expected). - Fix the class back, the page will reload (as expected).
Mix compile (doesn’t work)
mix phx.server
is not running.- Write an incorrect class
<body class={class(["bg-wh ite", "dark:bg-gray-900"])}>
. - Start
mix phx.server
, and it will raise an error. (as expected) - Fix the class back to
<body class={class(["bg-white", "dark:bg-gray-900"])}>
. - Run
mix phx.server
, and onlyPhoenixAssetPipelineExampleWeb.Layout
will be recompiled, and you will get an error:
To avoid this, you need to force recompiling PhoenixAssetPipeline.Helpers
.
Remove _build
folder or add __mix_recompile?__, do: true
to PhoenixAssetPipeline.Helpers
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Add
elixirc_options: [warnings_as_errors: true],