paulstatezny

paulstatezny

SurfaceFormatter - A code formatter for Surface, the component-based library for Phoenix LiveView

Hello everyone, I’ve just released a new library called SurfaceFormatter.

A special thanks to @msaraiva for his help and collaboration!

What is it?

SurfaceFormatter is a code formatter (like mix format) for Surface code.

If you’re not familiar with Surface, you can find it on Hex, GitHub, or the original ElixirForum post.

Why did I create it?

So that Surface developers can focus on building things without sacrificing valuable time and attention to make the code nicely formatted.

How does it work?

Add it to a Surface project, and run mix surface.format. That’s it!

Where can I find it?

A short example

Surface code that looks like this:

 <RootComponent with_many_attributes={{ true }} causing_this_line_to_wrap={{ true}} because_it_is_too_long={{ "yes" }}>
   <!-- An HTML comment -->
   {{#An Elixir comment}}



   <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}]}}>
  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"
>
  {{ # An Elixir comment }}

  <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}
  ]}}>
    Contents
  </Child>
</RootComponent>

Most Liked

paulstatezny

paulstatezny

SurfaceFormatter v0.2.1 has been released.

Previous versions didn’t allow inline elements to stay on the same line among text nodes, for example:

<p>
  I want <strong>this text</strong> to all stay on <em>one line</em>.
</p>

The previous rules were that each node (HTML element, text, or interpolation) would always be moved to a separate line. Therefore, this represents a pretty generous “relaxing” of the formatter. If anyone finds that it has become “too relaxed” in any scenarios, please post here and let me know!

paulstatezny

paulstatezny

SurfaceFormatter v0.7.0 was released. It comes packaged with a Formatter Plugin (available in Elixir 1.13) so that you can now run

$ mix format

to format both Elixir and Surface code in one command.

Special thanks to José Valim for adding Formatter Plugins to mix format! And to Marlus Saraiva for his part in it as well!

The next steps for SurfaceFormatter are:

  1. To merge it into Surface so that formatting works with even less setup out of the box.

  2. To attempt porting it into a HEEx formatter. As I understand it, formatting HEEx comes with some unique/extra technical challenges compared with Surface. We’ll see what happens. :slightly_smiling_face:

paulstatezny

paulstatezny

@Eiji Great observation :slight_smile:

Yes, the parsing library from Surface itself (which SurfaceFormatter uses under the hood) does not expose those comments, so we lose them. However, you can replace them with interpolated Elixir comments instead.

{{ # Some comment }}

I think it would be great to be able to keep HTML comments. If there is enough interest, perhaps the Surface parser can be modified to expose them.

In the meantime, I have added a more thorough explanation in that section of the docs to hopefully make the “why” more clear: https://hexdocs.pm/surface_formatter/Surface.Code.html#format_string!/2-html-comments

Where Next?

Popular in Announcing Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29305 241
New
josevalim
Yes, yet another parser combinator library! Most of the parser combinators in the ecosystem are either compile-time, often using AST tra...
159 19103 141
New
josevalim
EDIT: since Ecto 3.0 final version is out, this post was amended to use the final versions in the instructions below. Hi everyone, We a...
New
riverrun
I’ve just released version 3 of Comeonin, a password hashing library. The following small changes have been made: changes to the NIF c...
New
Crowdhailer
Experimenting with this code. OK.try do user &lt;- fetch_user(1) cart &lt;- fetch_cart(1) order = checkout(cart, user) save_or...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 13673 119
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
cjen07
parameterized pipe in elixir: |n&gt; edit: negative index in |n&gt; and mixed usage with |&gt; are supported example: use ParamP...
New
Crowdhailer
Raxx is an alternative to Plug and is inspired by projects such as Rack(Ruby) and Ring(Clojure). 1.0-rc.1 is now available. To use it re...
New
josevalim
Hello everyone, We have just released NimbleCSV which is a small and fast CSV parsing library for Elixir. It allows developers to define...
New

Other popular topics Top

stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
RisingFromAshes
I've read in another post that it may be possible with a router helper - but I couldn't find an appropriate one, and tbh, I'm still just ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement