Profile
Back to NewsBack
GitHub Trending 11 min
Reader Mode
ember-cli/eslint-plugin-ember: An ESLint plugin that provides set of rules for Ember applications based on commonly known good practices.

ember-cli/eslint-plugin-ember: An ESLint plugin that provides set of rules for Ember applications based on commonly known good practices.

15 hours ago

eslint-plugin-ember

NPM version</a> NPM downloads</a> !CI

An ESLint plugin that provides a set of rules for Ember applications based on commonly known good practices.

❗️Requirements

🚀 Usage

1. Install plugin

npm install --save-dev eslint-plugin-ember

2. Update your config

// eslint.config.js (flat config)
const eslintPluginEmberRecommended = require('eslint-plugin-ember/configs/recommended');

module.exports = [ ...eslintPluginEmberRecommended, ];

or

// .eslintrc.js (legacy config)
module.exports = {
  plugins: ['ember'],
  extends: [
    'eslint:recommended',
    'plugin:ember/recommended' // or other configuration
  ],
  rules: {
    // override / enable optional rules
    'ember/no-replace-test-comments': 'error'
  }
};

gts/gjs

lint files having First-Class Component Templates (fcct)

learn more at ember-template-imports

[!NOTE]
special care should be used when setting up parsers, since they cannot be overwritten. thus they should be used in override only and specific to file types

gjs/gts support is provided by the ember-eslint-parser

[!NOTE]
if you import .gts files in .ts files, then ember-eslint-parser is required for .ts as well to enable typed linting
// .eslintrc.js
module.exports = {
  overrides: [
    {
      files: ['*/.{js,ts}'],
      plugins: ['ember'],
      parser: '@typescript-eslint/parser',
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended', // or other configuration
      ],
      rules: {
        // override / enable optional rules
        'ember/no-replace-test-comments': 'error'
      }
    },
    {
      files: ['*/.gts'],
      parser: 'ember-eslint-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/recommended',
        'plugin:ember/recommended',
        'plugin:ember/recommended-gts',
      ],
    },
    {
      files: ['*/.gjs'],
      parser: 'ember-eslint-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended',
        'plugin:ember/recommended-gjs',
      ],
    },
    {
      files: ['tests/*/.{js,ts,gjs,gts}'],
      rules: {
        // override / enable optional rules
        'ember/no-replace-test-comments': 'error'
      }
    },
  ],
};

rules applied to fcct templates

  • semi rule, same as prettier plugin
  • no-undef rule will take effect for template vars (includes js scope)
  • no-unused rule will take effect for template block params
rules in templates can be disabled with eslint directives with mustache or html comments:
<template>
  <div>
    {{!eslint-disable-next-line}}
    {{test}}
  </div>
  <div>
    {{!--eslint-disable--}}
    {{test}}
    {{test}}
    {{test}}
    {{!--eslint-enable--}}
  </div>
</template>
<template>
  <div>
    <!--eslint-disable-next-line-->
    {{test}}
  </div>
  <div>
    <!-- eslint-disable -->
    {{test}}
    {{test}}
    {{test}}
    <!-- eslint-enable -->
  </div>
</template>

Migrating from ember-template-lint

If you are replacing ember-template-lint with this plugin, use the template-lint-migration config to get the equivalent set of rules:

// eslint.config.js (flat config)
import eslintPluginEmberRecommended from 'eslint-plugin-ember/configs/recommended';
import eslintPluginEmberTemplateLintMigration from 'eslint-plugin-ember/configs/template-lint-migration';

export default [ ...eslintPluginEmberRecommended, ...eslintPluginEmberTemplateLintMigration, { rules: { // Migrate custom overrides from your .template-lintrc.*: 'ember/template-no-bare-strings': ['error', { allowlist: ['×'] }], 'ember/template-no-inline-styles': 'off', }, }, ];

template-lint-migration mirrors the ember-template-lint recommended preset.

Linting .hbs files

ESLint flat config only picks up .hbs files when a files glob names them. Add a dedicated block so they route to the Handlebars parser:

// eslint.config.mjs
import { hbsParser, plugin as emberPlugin } from 'eslint-plugin-ember/recommended';

export default [ // ...other blocks... { files: ['app/*/.hbs'], languageOptions: { parser: hbsParser }, plugins: { ember: emberPlugin }, rules: { 'ember/template-no-bare-strings': 'error', // ...other template rules... }, }, ];

Make sure no earlier @typescript-eslint/parser block's files glob reaches .hbs — narrow it to ['*/.{js,ts,gjs,gts}'] (or similar). Flat config merges rules across every matching block, so even if our HBS block overrides the parser, type-info rules from a matching TS block still layer on and fail with errors like:

Parsing error: … was not found by the project service because the extension for the file (.hbs) is non-standard.

or

Error while loading rule @typescript-eslint/await-thenable: You have used a rule which requires type information.

Replacing template-lint-disable comments

Inline disable directives need to be rewritten to ESLint's syntax, prefixed with ember/template-. For now, only two scopes are supported: the next line, or the rest of the file. For example, replace:

{{!template-lint-disable no-invalid-role}}

with:

{{!eslint-disable-next-line ember/template-no-invalid-role}}

The template-no-template-lint-directives rule (enabled by the template-lint-migration config) does this rewrite for you: run eslint --fix once and it converts every template-lint-disable / template-lint-enable comment in your templates.

To disable a rule for an entire .gjs/.gts file, use a regular ESLint file-level directive in the JS region — it applies to the