A Prettier plugin for formatting Ember template tags in both .gjs
and .gts
files. See also Ember Template Imports.
Prettier 3.0.0 and above
-
Install:
NPM:
npm install --save-dev prettier prettier-plugin-ember-template-tag
Yarn:
yarn add --dev prettier prettier-plugin-ember-template-tag
PNPM:
pnpm add --save-dev prettier prettier-plugin-ember-template-tag
-
Configure prettier using your preferred method. For example, with
.prettierrc.js
:// .prettierrc.js module.exports = { // ... plugins: ['prettier-plugin-ember-template-tag'], overrides: [ { files: '*.{js,ts,gjs,gts}', options: { singleQuote: true, }, }, // ... ], };
If you already have a
"prettier"
section inpackage.json
, remember that takes precedence over the.prettierrc.js
file! -
Run
npm prettier --write . --plugin prettier-plugin-ember-template-tag
See ember-tooling#113 and prettier/prettier#15351 for details on why using the
--plugin
flag is required here.
This plugin works by weaving together Prettier's standard babel-ts and glimmer parsers, so it doesn't have many opinions of its own. With that said, I did have to make some opinionated decisions regarding how templates are printed within the JavaScript. In general, my strategy has been to ask "What would a function do?" since functions can be used in the same positions as the <template>
tag.
Semicolons will be included or omitted as follows:
export default class MyComponent extends Component {
<template>Hello</template> // omit
}
<template>Hello</template> // omit
export default <template>Hello</template> // omit
export const MyComponent = <template>Hello</template>; // include by default, omit in no-semi mode
You can read more about and comment on my semicolon decision process on this RFC.
Template tags will always be printed on their own line for templates that are default exports or top-level class templates. Templates used as expressions will be allowed to collapse onto a single line if they fit:
import Component from '@glimmer/component';
const what = <template>Used as an expression</template>;
export const who = <template>Used as an expression</template>;
<template>
The default export
</template>
class MyComponent extends Component {
<template>
Top-level class template
</template>
}
The following <template>
invocations both desugar to default exports:
// template-only-component.js
<template>Hello</template>;
// or
export default <template>Hello</template>;
By default, this plugin will remove export default
to print the more concise "sugared" default export template. If you would prefer to always include export default
, you can enable the templateExportDefault
option described below.
These configuration options are available in addition to Prettier's standard config for JavaScript and Handlebars files.
Name | Default | Description |
---|---|---|
templateExportDefault |
false |
If true , default export template tags will be prepended with export default . |
templateSingleQuote |
undefined | Same as in Prettier but affecting only template tags. If undefined , will fall back to whatever is set for the global singleQuote config. |
-
Install Prettier and this plugin as shown above.
-
Install the
Prettier - Code Formatter
VSCode Extension. -
Reload your VSCode window.
-
The format command and format-on-save should now work for
.gjs
and.gts
files. You might need to wait a few seconds for the Prettier extension to register the plugin. If this does not work, you can manually set Prettier as the default formatter for.gjs
and.gts
as shown below, like so, but please file an issue if you need to do this:// .vscode/settings.json { "[gjs]": { // "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[gts]": { // "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" } }
-
If you're still having issues, check out this issue for troubleshooting ideas and comment there with what ends up working.
Because gts/gjs files include both JavaScript and Glimmer template code, you'll need to use the appropriate prettier-ignore comment for the code you are ignoring:
export default class MyComponent extends Component {
// prettier-ignore
cells = matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
)
<template>
{{! prettier-ignore }}
{{#each this.cells as |cell|}}{{cell.contents}}{{/each}}
</template>
}
To ignore the entire template, use a JavaScript //prettier-ignore
comment before the opening <template>
tag:
export default class MyComponent extends Component {
// prettier-ignore
<template>
This whole template is ignored
<MyUglyComponent "shall" be="preserved">
<ThisPart
is = "also preserved as is"
/>
</MyUglyComponent>
</template>
}
If you find a bug, please file a bug report! See CONTRIBUTING.md for more details.