Home

Awesome

eslint-plugin-ember

NPM version NPM downloads 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 here

[!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

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>

🧰 Configurations

<!-- begin auto-generated configs list -->
Name
base
recommended
gjs logorecommended-gjs
gts logorecommended-gts
<!-- end auto-generated configs list -->

🍟 Rules

<!-- begin auto-generated rules list -->

💼 Configurations enabled in.
✅ Set in the recommended configuration.
gjs logo Set in the recommended-gjs configuration.
gts logo Set in the recommended-gts configuration.
🔧 Automatically fixable by the --fix CLI option.
💡 Manually fixable by editor suggestions.

Components

Name                        Description💼🔧💡
no-attrs-in-componentsdisallow usage of this.attrs in components
no-attrs-snapshotdisallow use of attrs snapshot in the didReceiveAttrs and didUpdateAttrs component hooks
no-classic-componentsenforce using Glimmer components
no-component-lifecycle-hooksdisallow usage of "classic" ember component lifecycle hooks. Render modifiers or custom functional modifiers should be used instead.
no-on-calls-in-componentsdisallow usage of on to call lifecycle hooks in components
require-tagless-componentsdisallow using the wrapper element of a component

Computed Properties

Name                                                           Description💼🔧💡
computed-property-gettersenforce the consistent use of getters in computed properties
no-arrow-function-computed-propertiesdisallow arrow functions in computed properties
no-assignment-of-untracked-properties-used-in-tracking-contextsdisallow assignment of untracked properties that are used as computed property dependencies🔧
no-computed-properties-in-native-classesdisallow using computed properties in native classes
no-deeply-nested-dependent-keys-with-eachdisallow usage of deeply-nested computed property dependent keys with @each
no-duplicate-dependent-keysdisallow repeating computed property dependent keys🔧
no-incorrect-computed-macrosdisallow incorrect usage of computed property macros🔧
no-invalid-dependent-keysdisallow invalid dependent keys in computed properties🔧
no-side-effectsdisallow unexpected side effects in computed properties
no-volatile-computed-propertiesdisallow volatile computed properties
require-computed-macrosrequire using computed property macros when possible🔧
require-computed-property-dependenciesrequire dependencies to be declared statically in computed properties🔧
require-return-from-computeddisallow missing return statements in computed properties
use-brace-expansionenforce usage of brace expansion in computed property dependent keys

Controllers

NameDescription💼🔧💡
alias-model-in-controllerenforce aliasing model in controllers
avoid-using-needs-in-controllersdisallow using needs in controllers
no-controllersdisallow non-essential controllers

Deprecations

NameDescription💼🔧💡
closure-actionsenforce usage of closure actions
new-module-importsenforce using "New Module Imports" from Ember RFC #176
no-array-prototype-extensionsdisallow usage of Ember's Array prototype extensions🔧
no-at-ember-render-modifiersdisallow importing from @ember/render-modifiers
no-deprecated-router-transition-methodsenforce usage of router service transition methods🔧
no-function-prototype-extensionsdisallow usage of Ember's function prototype extensions
no-implicit-injectionsenforce usage of implicit service injections🔧
no-mixinsdisallow the usage of mixins
no-new-mixinsdisallow the creation of new mixins
no-observersdisallow usage of observers
no-old-shimsdisallow usage of old shims for modules🔧
no-string-prototype-extensionsdisallow usage of String prototype extensions

Ember Data

Name                              Description💼🔧💡
no-empty-attrsdisallow usage of empty attributes in Ember Data models
require-async-inverse-relationshiprequire inverse to be specified in @belongsTo and @hasMany decorators
use-ember-data-rfc-395-importsenforce usage of @ember-data/ package imports instead ember-data🔧

Ember Object

Name                                Description💼🔧💡
avoid-leaking-state-in-ember-objectsdisallow state leakage
no-getrequire using ES5 getters instead of Ember's get / getProperties functions🔧
no-get-with-defaultdisallow usage of the Ember's getWithDefault function🔧
no-proxiesdisallow using array or object proxies
no-try-invokedisallow usage of the Ember's tryInvoke util
require-super-in-lifecycle-hooksrequire super to be called in lifecycle hooks🔧
use-ember-get-and-setenforce usage of Ember.get and Ember.set🔧

Ember Octane

Name                                Description💼🔧💡
classic-decorator-hooksenforce using correct hooks for both classic and non-classic classes
classic-decorator-no-classic-methodsdisallow usage of classic APIs such as get/set in classes that aren't explicitly decorated with @classic
no-actions-hashdisallow the actions hash in components, controllers, and routes
no-classic-classesdisallow "classic" classes in favor of native JS classes
no-ember-super-in-es-classesdisallow use of this._super in ES class methods🔧
no-empty-glimmer-component-classesdisallow empty backing classes for Glimmer components
no-tracked-properties-from-argsdisallow creating @tracked properties from this.args
template-indentenforce consistent indentation for gts/gjs templates🔧
template-no-let-referencedisallow referencing let variables in <template>gjs logo gts logo

jQuery

NameDescription💼🔧💡
jquery-ember-rundisallow usage of jQuery without an Ember run loop
no-global-jquerydisallow usage of global jQuery object
no-jquerydisallow any usage of jQuery

Miscellaneous

Name                                              Description💼🔧💡
named-functions-in-promisesenforce usage of named functions in promises
no-html-safedisallow the use of htmlSafe
no-incorrect-calls-with-inline-anonymous-functionsdisallow inline anonymous functions as arguments to debounce, once, and scheduleOnce
no-invalid-debug-function-argumentsdisallow usages of Ember's assert() / warn() / deprecate() functions that have the arguments passed in the wrong order.
no-restricted-property-modificationsdisallow modifying the specified properties🔧
no-runloopdisallow usage of @ember/runloop functions
require-fetch-importenforce explicit import for fetch()

Routes

Name                            Description💼🔧💡
no-capital-letters-in-routesdisallow routes with uppercased letters in router.js
no-controller-access-in-routesdisallow routes from accessing the controller outside of setupController/resetController
no-private-routing-servicedisallow injecting the private routing service
no-shadow-route-definitionenforce no route path definition shadowing
no-unnecessary-index-routedisallow unnecessary index route definition
no-unnecessary-route-path-optiondisallow unnecessary usage of the route path option🔧
route-path-styleenforce usage of kebab-case (instead of snake_case or camelCase) in route paths💡
routes-segments-snake-caseenforce usage of snake_cased dynamic segments in routes

Services

Name                                     Description💼🔧💡
no-implicit-service-injection-argumentdisallow omitting the injected service name argument🔧
no-restricted-service-injectionsdisallow injecting certain services under certain paths
no-unnecessary-service-injection-argumentdisallow unnecessary argument when injecting services🔧
no-unused-servicesdisallow unused service injections (see rule doc for limitations)💡

Stylistic Issues

NameDescription💼🔧💡
order-in-componentsenforce proper order of properties in components🔧
order-in-controllersenforce proper order of properties in controllers🔧
order-in-modelsenforce proper order of properties in models🔧
order-in-routesenforce proper order of properties in routes🔧

Testing

Name                                      Description💼🔧💡
no-current-route-namedisallow usage of the currentRouteName() test helper
no-ember-testing-in-module-scopedisallow use of Ember.testing in module scope
no-invalid-test-waitersdisallow incorrect usage of test waiter APIs
no-legacy-test-waitersdisallow the use of the legacy test waiter APIs
no-noop-setup-on-error-in-beforedisallows using no-op setupOnerror in before or beforeEach🔧
no-pause-testdisallow usage of the pauseTest helper in tests
no-replace-test-commentsdisallow 'Replace this with your real tests' comments in test files
no-restricted-resolver-testsdisallow the use of patterns that use the restricted resolver in tests
no-settled-after-test-helperdisallow usage of await settled() right after test helper that calls it internally🔧
no-test-and-thendisallow usage of the andThen test wait helper
no-test-import-exportdisallow importing of "-test.js" in a test file and exporting from a test file
no-test-module-fordisallow usage of moduleFor, moduleForComponent, etc
no-test-support-importdisallow importing of "test-support" files in production code.
no-test-this-renderdisallow usage of the this.render in tests, recommending to use @ember/test-helpers' render instead.
prefer-ember-test-helpersenforce usage of @ember/test-helpers methods over native window methods
require-valid-css-selector-in-test-helpersdisallow using invalid CSS selectors in test helpers🔧
<!-- end auto-generated rules list -->

🍻 Contribution Guide

If you have any suggestions, ideas, or problems, feel free to create an issue, but first please make sure your question does not repeat previous ones.

Creating a New Rule

Note that new rules should not immediately be added to the recommended configuration, as we only consider such breaking changes during major version updates.

🔓 License

See the LICENSE file for license rights and limitations (MIT).