Skip to content

Latest commit

 

History

History
361 lines (296 loc) · 32.5 KB

README.md

File metadata and controls

361 lines (296 loc) · 32.5 KB

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

  • 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>

🧰 Configurations

Name
base
recommended
gjs logo recommended-gjs
gts logo recommended-gts

🍟 Rules

💼 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-components disallow usage of this.attrs in components
no-attrs-snapshot disallow use of attrs snapshot in the didReceiveAttrs and didUpdateAttrs component hooks
no-classic-components enforce using Glimmer components
no-component-lifecycle-hooks disallow usage of "classic" ember component lifecycle hooks. Render modifiers or custom functional modifiers should be used instead.
no-on-calls-in-components disallow usage of on to call lifecycle hooks in components
require-tagless-components disallow using the wrapper element of a component

Computed Properties

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

Controllers

Name Description 💼 🔧 💡
alias-model-in-controller enforce aliasing model in controllers
avoid-using-needs-in-controllers disallow using needs in controllers
no-controllers disallow non-essential controllers

Deprecations

Name Description 💼 🔧 💡
closure-actions enforce usage of closure actions
new-module-imports enforce using "New Module Imports" from Ember RFC #176
no-array-prototype-extensions disallow usage of Ember's Array prototype extensions 🔧
no-at-ember-render-modifiers disallow importing from @ember/render-modifiers
no-deprecated-router-transition-methods enforce usage of router service transition methods 🔧
no-function-prototype-extensions disallow usage of Ember's function prototype extensions
no-implicit-injections enforce usage of implicit service injections 🔧
no-mixins disallow the usage of mixins
no-new-mixins disallow the creation of new mixins
no-observers disallow usage of observers
no-old-shims disallow usage of old shims for modules 🔧
no-string-prototype-extensions disallow usage of String prototype extensions

Ember Data

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

Ember Object

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

Ember Octane

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

jQuery

Name Description 💼 🔧 💡
jquery-ember-run disallow usage of jQuery without an Ember run loop
no-global-jquery disallow usage of global jQuery object
no-jquery disallow any usage of jQuery

Miscellaneous

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

Routes

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

Services

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

Stylistic Issues

Name Description 💼 🔧 💡
order-in-components enforce proper order of properties in components 🔧
order-in-controllers enforce proper order of properties in controllers 🔧
order-in-models enforce proper order of properties in models 🔧
order-in-routes enforce proper order of properties in routes 🔧

Testing

Name                                       Description 💼 🔧 💡
no-current-route-name disallow usage of the currentRouteName() test helper
no-ember-testing-in-module-scope disallow use of Ember.testing in module scope
no-invalid-test-waiters disallow incorrect usage of test waiter APIs
no-legacy-test-waiters disallow the use of the legacy test waiter APIs
no-noop-setup-on-error-in-before disallows using no-op setupOnerror in before or beforeEach 🔧
no-pause-test disallow usage of the pauseTest helper in tests
no-replace-test-comments disallow 'Replace this with your real tests' comments in test files
no-restricted-resolver-tests disallow the use of patterns that use the restricted resolver in tests
no-settled-after-test-helper disallow usage of await settled() right after test helper that calls it internally 🔧
no-test-and-then disallow usage of the andThen test wait helper
no-test-import-export disallow importing of "-test.js" in a test file and exporting from a test file
no-test-module-for disallow usage of moduleFor, moduleForComponent, etc
no-test-support-import disallow importing of "test-support" files in production code.
no-test-this-render disallow usage of the this.render in tests, recommending to use @ember/test-helpers' render instead.
prefer-ember-test-helpers enforce usage of @ember/test-helpers methods over native window methods
require-valid-css-selector-in-test-helpers disallow using invalid CSS selectors in test helpers 🔧

🍻 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

  • Create an issue with a description of the proposed rule
  • Create files for the new rule:
    • lib/rules/new-rule.js (implementation, see no-proxies for an example)
    • docs/rules/new-rule.md (documentation, start from the template -- raw, rendered)
    • tests/lib/rules/new-rule.js (tests, see no-proxies for an example)
  • Run pnpm update to automatically update the README and other files (and re-run this if you change the rule name or description)
  • Make sure your changes will pass CI by running:
    • pnpm test
    • pnpm lint (pnpm lint:js --fix can fix many errors)
  • Create a PR and link the created issue in the description

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).