Formatter for HEEx templates

Hello folks! Are there any libraries for formatting of HEEx templates?

1 Like

there is the “phoenixframework” addin for VS-Code but it does only highlighting.

see this twitter thread

so basically “soon”…


I noticed that Emacs web-mode does a great job at indenting HEEx templates out of the box, but since I’m not a Emacs user, I wrapped that in a script that works a bit like Prettier would

web-mode somehow understands well nested code blocks with Elixir conditions, loops and so on which I found pretty impressive (it only required a quick hack to work with the <.tag></.tag> notation).

It’s only for indentation though but that a pretty good start for me instead of having no formatter at all, at least until mix format can work with HEEx files!

1 Like

Another similar discussion here.

1 Like

This got merged recently!

1 Like

I use doom emacs, and I use the default web-mode indent. It seems to either understand the context of the heex file or ignores it, but it indents correctly without breakages.

You can use the Royal Mist Elixir Templates Formatter, and add to languages, "phoenix-hex":"html" in your VSCode settings.json like so:

"[phoenix-heex]": {
        "editor.defaultFormatter": "RoyalMist.vscode-eex-format"

Ah, you should also be able to do this in the settings user interface.

Basically this formatter uses htmlbeautifier gem under the hood. That has two disadvantages - additionally ruby has to be installed. Secondly, htmlbeautifier does not understand some of the embedded tags - so formatting goes wayward in a few cases.
The inbuilt mix format that is coming in is a tool from the same ecosystem - hence probably the best solution.


htmlbeautifier does not understand some of the embedded tags - so formatting goes wayward in a few cases.

Thanks, yeah I can only agree. The wayward formatting annoys me too, especially forms I guess? It seemed the best I could find. Looking forward to the inbuilt formatter also!

1 Like

GitHub - feliperenan/heex_formatter: Formatter for Phoenix Live View templates. is out and working well with elixir 1.13
It is working well with both ~H sigil and heex files.


Little late to this post, but it’s now part of the phoenix_live_view library, so it’s easier to setup in a existing Phoenix project. the heex formatter can be configured with the mix format task with the following config in the .formatter.exs file:

plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: [
  "*.{heex,ex,exs}", # <- include heex here 
  "{config,lib,test}/**/*.{heex,ex,exs}" # <- include heex here 

Here’s my setup which seems to be working nicely.

Suggested tweaks welcome!


Exactly what I was looking for; thank you!


Did you manage to get Tailwind Prettier integration working?

It seems to be pretty much impossible atm. I’ve tried GitHub - adamzapasnik/prettier-plugin-eex: Prettier EEX plugin and it blew up on slots.

npx prettier --config .prettierrc.js sample.html.heex --tailwind-config=tailwind.config.js
sample.html.heex [error] sample.html.heex: SyntaxError: Unexpected closing tag "icon". It may happen when the tag has already been closed by another tag. For more info see (81:21)
[error]   79 |                     <:icon>
[error]   80 |                       <MVIcons.x />
[error] > 81 |                     </:icon>
[error]      |                     ^^^^^^^^
[error]   82 |                     <:text>
[error]   83 |                       CANCEL
[error]   84 |                     </:text>

If you’re looking for a sorter, I’ve made one that integrates with mix format which may be of interest to you :slight_smile:

1 Like

@valerian could you share how did you make web-mode understand <.tag> as a tag.
I’ve changed the web-mode-tag-regexp and web-mode-start-tag-regexp but this does not seem to work…

In my case I didn’t need web-mode to understand them, I just cared about them being formatted by my CLI wrapper, so the hack was to replace the dot by some unique string, feeding that to web-mode for formatting, then replacing the unique string by a dot again :sweat_smile:

Ay! Thanks for clarification!