A code formatter for https://hex.pm/packages/surface.
The complete documentation for SurfaceFormatter is located here.
Add :surface_formatter
as a dependency in mix.exs
:
defp deps do
[
{:surface_formatter, "~> 0.7.5"}
]
end
Modify the following in .formatter.exs
:
inputs
- add patterns for all Surface filesplugins
- addSurface.Formatter.Plugin
# .formatter.exs
[
...,
# match all .sface files and all .ex files with ~F sigils
inputs: ["lib/**/*.{ex,sface}", ...],
plugins: [Surface.Formatter.Plugin]
]
For documentation of other .formatter.exs
options, see Surface.Formatter.Plugin
.
$ mix format
(Formats both Elixir and Surface code.)
Add surface_inputs
to .formatter.exs
with patterns for all Surface files:
# .formatter.exs
[
...,
# match all .sface files and all .ex files with ~F sigils
surface_inputs: ["lib/**/*.{ex,sface}", ...]
]
If your project does not use sface
files, you can omit :surface_inputs
and
specify file patterns in the standard :inputs
field instead. (mix surface.format
will fall back to :inputs
.) But be warned that including
.sface
files in :inputs
causes mix format
to crash in Elixir 1.12 and
earlier.
For documentation of other .formatter.exs
options, see mix surface.format
.
$ mix surface.format
The formatter mostly follows these rules:
- Only formats code inside of
~F"""
blocks and.sface
files. - Child nodes are typically indented 2 spaces in from their parent.
- Interpolated Elixir code (inside
{ }
brackets) is formatted by the official Elixir formatter. - HTML attributes are put on separate lines if the line is too long.
- Retains "lack of whitespace" such as
<p>No whitespace between text and tags</p>
. - Collapses extra newlines down to at most one blank line.
See Surface.Formatter.format_string!/2
for further documentation.
Out of the box, Surface code that looks like this:
<RootComponent with_many_attributes={ true } causing_this_line_to_wrap={ true} because_it_is_too_long={ "yes, this line is long enough to wrap" }>
<!-- HTML public comment (hits the browser) -->
{!-- Surface private comment (does not hit the browser) --}
<div :if={ @show_div }
class="container">
<p> Text inside paragraph </p>
<span>Text touching parent tags</span>
</div>
<Child items={[%{name: "Option 1", key: 1}, %{name: "Option 2", key: 2}, %{name: "Option 3", key: 3}, %{name: "Option 4", key: 4}]}>
Default slot contents
</Child>
</RootComponent>
will be formatted like this:
<RootComponent
with_many_attributes
causing_this_line_to_wrap
because_it_is_too_long="yes, this line is long enough to wrap"
>
<!-- HTML public comment (hits the browser) -->
{!-- Surface private comment (does not hit the browser) --}
<div :if={@show_div} class="container">
<p>
Text inside paragraph
</p>
<span>Text touching parent tags</span>
</div>
<Child items={[
%{name: "Option 1", key: 1},
%{name: "Option 2", key: 2},
%{name: "Option 3", key: 3},
%{name: "Option 4", key: 4}
]}>
Default slot contents
</Child>
</RootComponent>