Format Glimmer templates with Prettier
Tags: ember, prettier, vscode
Published: 2021-02-07 22:04:27

[Prettier](https://prettier.io/) is an opinionated code formatter. It helps developers and teams to stop worry about coding style. Prettier allows developers to write code without manually formatting it for readability. Instead Prettier takes over after the developer has implemented the feature and rewrites the code with a set of opinionated rules tested by many applications in production.

[Ember](https://emberjs.com/) projects get a ready to be used Prettier configuration out of the box. Ember CLI [v3.24](https://blog.emberjs.com/ember-3-24-released), which was released in the first days of this year, include Prettier in the blueprints for applications and addons. New projects use it from day one. Existing projects can adopt prettier by updating the blueprints using [Ember CLI Update](https://cli.emberjs.com/release/basic-use/upgrading/).

By default Prettier is only enabled for JavaScript files. Prettier is not enabled for Glimmer templates. The glimmer parser included in Prettier is not yet officially released. It still includes some minor bugs. But many projects are already using it successfully nevertheless.

This blog post describes how Prettier can be configured to format Glimmer templates as well. Additionally it describes how VSCode needs to be configured to format Glimmer templates with Prettier on save.

## Linting Glimmer templates with Prettier

Ember CLI configures Prettier to run as an ESLint plugin. But ESLint is not used for Glimmer templates. The Ember ecosystem has it's developed a dedicated linter for Glimmer templates: [Ember Template Lint](https://github.com/ember-template-lint/ember-template-lint) Both ESLint and Ember Template Lint are included, configured and enabled for Ember projects by default.

Similar to how Prettier is run as ESLint plugin for JavaScript files it could be run as a plugin for Ember Template Lint. Ember community provides an official plugin to do so: [ember-template-lint-plugin-prettier](https://github.com/ember-template-lint/ember-template-lint-plugin-prettier).

The plugin adds Prettier as a template lint rule. The rule ensures that template linting fails if any Glimmer template (`*.hbs`) is not formatted with Prettier.

It is installed with as any other dependency with the package manager used by your project:

```sh
# if using yarn
yarn add -D prettier ember-template-lint-plugin-prettier

# if using NPM
npm install --save-dev ember-template-lint-plugin-prettier
```

Additionally it needs to be configured in template lint configuration of your project:

```patch
diff --git a/.template-lintrc.js b/.template-lintrc.js
index 3b0b9af..73c6c78 100644
--- a/.template-lintrc.js
+++ b/.template-lintrc.js
@@ -1,5 +1,6 @@
 'use strict';
 
 module.exports = {
-  extends: 'octane',
+  plugins: ['ember-template-lint-plugin-prettier'],
+  extends: ['octane', 'ember-template-lint-plugin-prettier:recommended'],
 };
```

Afterwards `yarn lint:hbs` will complain if any Glimmer template is not formatted with Prettier.

The application template created by Ember CLI is not formatted with Prettier. If you configured the Prettier plugin for Ember Template Lint successfully, you will see the following linting violation for a new application created with Ember CLI v3.24:

```sh
$ yarn lint:hbs
yarn run v1.22.5
$ ember-template-lint .
app/templates/application.hbs
  1:13  error  Replace `"EmberProjectUsingPrettierForTemplates"` with `'EmberProjectUsingPrettierForTemplates'`  prettier
  3:3  error  Replace `--·The·following·component·displays·Ember's·default·welcome·message.·--` with ` The following component displays Ember's default welcome message. `  prettier
  5:3  error  Replace `--·Feel·free·to·remove·this!·--` with ` Feel free to remove this! `  prettier

✖ 3 problems (3 errors, 0 warnings)
  3 errors and 0 warnings potentially fixable with the `--fix` option.
```

## Using double quotes in Glimmer templates but single quotes in JavaScript files

The Ember community has an informal convention to use single quotes in JavaScript files but double quotes in Glimmer templates. It is reflected in official guides and used by new projects.

Prettier is configured to use single quotes in a new Ember project. This is controlled by `.prettierrc.js` created by Ember CLI blueprints:

```js
'use strict';

module.exports = {
  singleQuote: true,
};
```

Prettier follows that configuration and also complains about double quotes used in Glimmer templates. We need to update the Prettier configuration to follow the Ember community convention and use single quotes in JavaScript files but double quotes in Glimmer templates.

We can do so adding an override of the default configuration for `*.hbs` files.

```patch
diff --git a/.prettierrc.js b/.prettierrc.js
index 534e6d3..09f6af7 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -2,4 +2,12 @@
 
 module.exports = {
   singleQuote: true,
+  overrides: [
+    {
+      files: '*.hbs',
+      options: {
+        singleQuote: false,
+      },
+    },
+  ],
 };
```

Running `yarn lint:hbs` again on our new project it stops complaining about double quotes being used. 💪

But it still complains about using wrong comment style at two places:

```sh
$ yarn lint:hbs
yarn run v1.22.5
$ ember-template-lint .
app/templates/application.hbs
  3:3  error  Replace `--·The·following·component·displays·Ember's·default·welcome·message.·--` with ` The following component displays Ember's default welcome message. `  prettier
  5:3  error  Replace `--·Feel·free·to·remove·this!·--` with ` Feel free to remove this! `  prettier

✖ 2 problems (2 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

Let's find out how we can run Prettier to fix that violations automatically.

## Formatting Glimmer templates with Prettier

JavaScript files can be formatted with Prettier running `yarn lint:js:fix`. This executes `eslint` with `--fix` flag. As described above ESLint runs Prettier as a plugin and formats the JavaScript files with it.

Similar Ember projects support `yarn lint:hbs:fix` command to fix linting errors in Glimmer templates. It executes `ember-template-lint` with `--fix` flag. And as thanks to Prettier plugin for Ember Template Lint, which we added earlier, that command tells Prettier to format the Glimmer templates.

```sh
$ yarn lint:hbs:fix
yarn run v1.22.5
$ ember-template-lint . --fix
Done in 0.43s.
```

After running it the `app/templates/application.hbs` is formatted with Prettier. 🎉

```patch
$ git diff app/templates/application.hbs
diff --git a/app/templates/application.hbs b/app/templates/application.hbs
index 6f0ea67..298858c 100644
--- a/app/templates/application.hbs
+++ b/app/templates/application.hbs
@@ -1,7 +1,7 @@
 {{page-title "EmberProjectUsingPrettierForTemplates"}}
 
-{{!-- The following component displays Ember's default welcome message. --}}
+{{! The following component displays Ember's default welcome message. }}
 <WelcomePage />
-{{!-- Feel free to remove this! --}}
+{{! Feel free to remove this! }}
 
 {{outlet}}
\ No newline at end of file
```

## Format JavaScript files with Prettier on save in VSCode

I'm lazy. I don't want to run `yarn lint:js:fix` manually. Therefore I configured VSCode to fix ESLint violations automatically when I save a file. I guess I'm not the only lazy developer. So let me explain you how that could be done.

First of all we need to install [ESLint extension for VSCode](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). Out of the box that extension will show ESLint violates in VSCode while you are typing.

By default it does not fix linting errors on save automatically. To do so the configuration needs to be adjusted. To do so open the VSCode settings and add the following configuration:

```json
"editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
}
```

Please refer to [official documentation](https://github.com/Microsoft/vscode-eslint#settings-options) for ESLint extension for VSCode for details.

How to do the same for Glimmer Templates?

## Format Glimmer templates with Prettier in VSCode

There is no official VSCode extension for Ember Template Lint as far as I know. But we can use [Prettier for VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) to achieve the same.

After installing the extension it needs to be configured to format Glimmer templates. As the Glimmer parser is not officially released yet, Prettier disables it by default. Therefore we need to tell Prettier explicitly to use it for Glimmer templates. To do so we need to update the Prettier configuration:

```patch
diff --git a/.prettierrc.js b/.prettierrc.js
index 09f6af7..919bd65 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -6,6 +6,7 @@ module.exports = {
     {
       files: '*.hbs',
       options: {
+        parser: 'glimmer',
         singleQuote: false,
       },
     },
```

Additionally we need to configure the VSCode extension for Prettier to be active for `.hbs` files. We can do so by setting [`prettier.documentSelectors`](https://github.com/prettier/prettier-vscode#prettierdocumentselectors) configuration option in VSCode settings.

```json
{
  "prettier.documentSelectors": ["**/*.hbs"],
}
```

Afterwards Prettier is available as a formatter for Glimmer templates in VSCode.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0irkm68x2b5bw0up1533.gif)

But we need to trigger the formatting manually. We also need to select Prettier formatter explicitly. These are way more manually steps than I want to do as the lazy developer that I am.

Let's configure VSCode to format Glimmer templates with Prettier on save as we already have it for JavaScript files. As a first step we tell VSCode to use Prettier as default formatter for Glimmer templates. To do so we need to add another line to  VSCode settings:

```json
"[handlebars]": {
   "editor.defaultFormatter": "esbenp.prettier-vscode",
},
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fxcdz1x1owod9qi2zzqx.gif)

We don't need to select Prettier formatter explicitly anymore. But we still need to run the formatting manually. Let's additonally enable format on save for Glimmer templates:

```json
"[handlebars]": {
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true
},
```

As JavaScript files are formatted by ESLint with a code action on save we don't want to enable `editor.formatOnSave` globally.

## Summary

Glimmer templates of our project are now formatted with Prettier. We can run it manually with `yarn lint:hbs:fix`. But Prettier is also run automatically when saving a template in VSCode. Additionally Ember Template Lint complains if for whatever reason a template is not formatted with Prettier. 🎉

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pz3akg3ozpapl96d22f2.gif)

Thanks a lot to Georgii Dolzhykov ([@thornO](https://github.com/thorn0)) who [showed me](https://github.com/prettier/prettier/issues/10263#issuecomment-774745393) how to configure Prettier and VSCode extension for Prettier to format Glimmer templates. And of course to all the great people both from Ember and Prettier community, who created the great tool and worked on adding Glimmer support [over the last three years](https://github.com/prettier/prettier/issues/4908).

If you have any question, know a potential improvement or found an error please do not hesitate to reach out to me either via comment here or in #topic-editors channel on [Ember Discord](https://discord.gg/emberjs).