A Prettier Handlebars

May 07, 2020

It seems like all developers, myself included, love to have an opinion on how code should be formatted. In order to be more productive I would happily give up the hours discussing personal style and hand over the responsibility to an opinionated tool. Prettier is that tool. It knows how your code should be formatted, removing the luxury of a personal style, and is able to go ahead and format your code. This is especially useful for those languages that don’t ship with an opinionated formatter, like javascript. Prettier comes with very few customizations leaving little to be debated amongst the team. I also love that there are editor integrations that keep your code looking pretty automatically as you go.

Prettier has support for a few languages out of the box and for others there are unofficial plugins available. The handlebars language, or Glimmer as its modern extension is called in Ember, is part of the core prettier package and has had a semi-working implementation for a few years now. As I often work in Ember codebases I was excited to learn from a co-worker about his effort to rally support behind picking up the “Prettier for handlebars” torch. Thanks to his “Quest Issue”, a meta checklist and discussion thread, as a community we are able to coordinate our efforts in identifying and tackling the remaining bugs.

I hadn’t worked on code formatters before so I was excited to give it a go. My first contribution was better whitespace control which ended up covering more cases than I expected. It was sort of like a thread, as you pulled you realized how a lot of the whitespace logic was all connected. Luckily, Prettier gives you a handy set of abstractions to use. The basis of these tools is: given an AST node, and an interface for checking its neighbors, you must annotate the node with “printers”. These printers are a declarative way of describing to prettier how the node should be printed, or formatted. For example, this includes how lines should break when you hit a max character length width, and how to handle code blocks and intention.

The trickiest part, in my opinion, about developing with prettier is distilling the personal conventions of the community and what should be codified in Prettier. Since the prettier project uses jest’s snapshot for testing it’s easy-ish to browse the test suite and see the current state and what effects your changes will have. This helps to identify what style has already been established (or what might stand out as a bug and hasn’t been fixed yet as in the case of handlebars’ current unfinished progress). While the test suite prevented unwanted regressions I found that taking a best guess and letting people try the prettier playground, an interactive way of pasting code and seeing how prettier will format it, was the easiest way of getting feedback.

After my PR for whitespace improvements landed I took a few months before revisiting the Quest Issue to check up on the community’s progress. This time I though it would be interesting to work on prettier-ignore for handlebars, a code comment that signals to prettier that you do not want it to format the next node, nor its children, and to leave it as is. Using prettier-ignore is useful for when whitespace should be preserved in your handlebars templates. Since Prettier for handlebars is still a work in progress, it also comes in handy to ignore a prettier formatting bug that hasn’t been fixed yet. I was able to copy a similar design from other prettier language implementations. I’m happy to say that ignoring formatting is much easier than applying it.

Thanks to the contributors who worked on the quest issue and those that worked on the original implementation prior, we are actually getting pretty close to being able to recommend Prettier for handlesbars for production codebases. If you’re at all interested please reach out and comment on the Quest Issue. I’m looking forward to a productive, prettier future!