View Source Code Transformations
During mix uniform.eject
, there are 4 code transformations applied to file
contents. These transformations happen to every file except those ejected with
cp
and cp_r
.
They occur in this order.
- Unused mix.exs Dependencies are Removed
- Blueprint Modifiers are ran
- The Base Project Name is replaced with the ejected app's name
- Eject Fences are processed
mix-exs-dependency-removal
mix.exs Dependency Removal
Any Mix Dependency that is not directly or indirectly required by the app via
uniform.exs
or the Blueprint
module is removed from the ejected mix.exs
.
blueprint-modifiers
Blueprint Modifiers
Users can specify arbitrary modifications that should be applied to various
files using the modify
macro in the Blueprint module:
modify ~r/.+_worker.ex/, fn file, app ->
# `file` is a string containing the full file contents.
# `app` is the `Uniform.App` struct. (The app being ejected.)
# The string this function returns will be the ejected file contents.
end
modify "lib/my_app_web/router.ex", fn file ->
# This modifier is like the one above, but the transformation will only
# be ran for `lib/my_app_web/router.ex`.
end
replacing-the-base-project-name
Replacing the Base Project Name
The base project name, appearing anywhere in a file, is replaced by the ejected
app name. This applies to the following formats: base_app
, base-app
, and
BaseApp
.
The base project name is the :app
key returned by project
in the mix.exs
file of the Base Project. (For example, :my_base_app
below.)
# mix.exs
def project do
[
app: :my_base_app, # <- base project name
...
]
end
Given the above mix.exs
, if you were to run mix uniform.eject my_ejectable_app
:
my_base_app
would be replaced withmy_ejectable_app
my-base-app
would be replaced withmy-ejectable-app
MyBaseApp
would be replaced withMyEjectableApp
Replacement in file paths
This same replacement of
base_project_name
toejected_app_name
also occurs in file paths, but only withthis_format
. (Notthis-format
orThisFormat
.)This means a file at
lib/base_project_name/foo.ex
would be ejected tolib/ejected_app_name/foo.ex
.
This means that a file like this
defmodule MyBaseAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_base_app
socket "/socket", MyBaseAppWeb.UserSocket,
websocket: true,
longpoll: false
plug MyBaseAppWeb.Router
end
Would be transformed to this
defmodule MyEjectableAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_ejectable_app
socket "/socket", MyEjectableAppWeb.UserSocket,
websocket: true,
longpoll: false
plug MyEjectableAppWeb.Router
end
eject-fences
Eject Fences
In any .ex
or .exs
file, you can use "Eject Fence" comments to remove code
unless certain criteria are met.
To remove code unless the ejected app depends on a Lib Dependency called
my_lib
, wrap it in these comments:
# uniform:lib:my_lib
# ... code
# /uniform:lib:my_lib
To remove code unless the ejected app depends on a Mix Dependency called
absinthe
, wrap it in these comments:
# uniform:mix:absinthe
# ... code
# /uniform:mix:absinthe
To remove code unless the ejected app is called MyApp
, wrap it in these
comments:
# uniform:app:my_app
# ... code
# /uniform:app:my_app
Finally, to always remove a chunk of code whenever ejection happens, wrap it in these comments:
# uniform:remove
# ... code
# /uniform:remove
Eject Fence comments are always removed
Regardless of whether
mix uniform.eject
keeps or deletes the code in an eject fence, the eject fence comments themselves (like# uniform:app:my_app
) are always removed.Furthermore,
mix uniform.eject
runsmix format
on the ejected codebase at the end. So you always end up with "clean" looking code.
eject-fences-for-other-languages
Eject Fences for other languages
Eject Fences are also processed for .js
/.ts
/.jsx
/.tsx
files using JS
single-line comments.
// uniform:lib:my_lib
// ...
// /uniform:lib:my_lib
If you would like to support Eject Fences for other languages or file types, you
can do so using Uniform.Modifiers.eject_fences/3
.
# eject fences for SQL files
modify ~r/\.sql$/, fn file, app ->
eject_fences(file, app, "--")
end
# eject fences for Rust files
modify ~r/\.rs$/, &eject_fences(&1, &2, "//")
# eject fences for CSS files
modify ~r/\.css$/, &eject_fences(&1, &2, "/\\*", "\\*/")
disabling-code-transformations
Disabling Code Transformations
If you have a file that should not have Code Transformations applied upon
ejection, use cp
instead of
file
.
If there is an entire directory of contents that should not be modified, use
cp_r
, which will be much faster.