angular-eslint

by angular-eslint

angular-eslint / angular-eslint

:sparkles: Monorepo for all the tooling related to using ESLint with Angular

339 Stars 41 Forks Last release: 26 days ago (v0.5.0-beta.1) MIT License 105 Commits 29 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

Angular ESLint

Monorepo for all the tooling which enables ESLint to lint Angular projects

Build Status NPM Version GitHub license NPM Downloads Codecov Commitizen friendly


This project is made possible thanks to the continued hard work going into https://github.com/typescript-eslint/typescript-eslint, and brilliant work on the original TSLint rule implementations in https://github.com/mgechev/codelyzer.

Feel free to begin playing with the tooling in your own projects and submit PRs with missing rules and bug fixes.

We would also be very grateful for documentation PRs!


Packages included in this project

Please follow the links below for the packages you care about.

  • @angular-eslint/builder
    - An Angular CLI Builder which is used to execute ESLint on your Angular projects using standard commands such as

    ng lint
  • @angular-eslint/eslint-plugin
    - An ESLint-specific plugin that contains rules which are specific to Angular projects. It can be combined with any other ESLint plugins in the normal way.

  • @angular-eslint/template-parser
    - An ESLint-specific parser which leverages the

    @angular/compiler
    to allow for custom ESLint rules to be written which assert things about your Angular templates.
  • @angular-eslint/eslint-plugin-template
    - An ESLint-specific plugin which, when used in conjunction with

    @angular-eslint/template-parser
    , allows for Angular template-specific linting rules to run.
  • @angular-eslint/schematics
    - Schematics which are used to add and update configuration files which are relevant for running ESLint on an Angular workspace.


Migrating from Codelyzer and TSLint

We have some work in progress tooling to make this as automated as possible, but the reality is it will always be somewhat project-specific as to how much work will be involved in the migration.

Step 1 - Add relevant dependencies

The first step is to run the schematic to add

@angular-eslint
to your project:
ng add @angular-eslint/schematics

This will handle installing the latest version of all the relevant packages for you and adding them to the

devDependencies
of your
package.json
.

Step 2 - Add new ESLint-related configuration

The next thing to do is consider which "project" you want to migrate to use ESLint. If you have a single application in your workspace you will likely have just a single entry in the

projects
configuration object within your
angular.json
file. If you have a
projects/
directory in your workspace, you will have multiple entires in your
projects
configuration and you will need to chose which one you want to migrate using the
add-config-to-project
schematic.

You can run it like so:

ng g @angular-eslint/schematics:add-config-to-project {{YOUR_PROJECT_NAME_GOES_HERE}}

The schematic will do the following for you:

  • CREATE a
    .eslintrc.json
    at the root of the specific project which extends from the root config (if you do not already have a root config, it will also add one automatically for you)
  • UPDATE the project's
    architect
    configuration in the
    angular.json
    to add a new target called
    eslint

You can run the new target like so:

npx ng run {{YOUR_PROJECT_NAME_GOES_HERE}}:eslint

This command uses the Angular CLI's standard tooling to invoke the

builder
from this project and ultimately run ESLint on the files which are relevant to your chosen project.

As this stage you have both TSLint and ESLint configured as different targets for your project - we have not removed or changed TSLint in any way.

Step 3 - Use the new ESLint configuration files to match your original TSLint configuration, or change it however you would like

Currently this is a manual step, but we hope to create a schematic to assist with this process soon. See Notes on ESLint Configuration below for some more info.

Step 4 - Remove TSLint configuration and use only ESLint

Once you are happy with your ESLint setup, you simply need to remove the project specific

tslint.json
and the
lint
configuration block within the project's
architect
configuration block in your
angular.json
.

Then you need to rename your

eslint
target to just
lint
and it will work as you are used to via:
npx ng run {{YOUR_PROJECT_NAME_GOES_HERE}}:lint

OR

npx ng lint {{YOUR_PROJECT_NAME_GOES_HERE}}


Notes on ESLint Configuration

It's important to understand up front that using Angular with ESLint is actually an advanced/complex use-case because of the nature of the files involved:

  • Angular projects use TypeScript files for source code
  • Angular projects use a custom/extended form of HTML for templates (be they inline or external HTML files)

The thing is: ESLint understands neither of these things out of the box.

Fortunately, however, ESLint has clearly defined points of extensibility that we can leverage to make this all work.

For detailed information about ESLint plugins, parsers etc please review the official ESLint documentation: https://eslint.org

The key principal of our configuration required for Angular projects is that we need to run different blocks of configuration for different file types/extensions. In other words, we don't want the same rules to apply on TypeScript files that we do on HTML/inline-templates.

Therefore, the critical part of our configuration is the

"overrides"
array:
{
  "overrides": [
    /**
     * -----------------------------------------------------
     * TYPESCRIPT FILES (COMPONENTS, SERVICES ETC) (.ts)
     * -----------------------------------------------------
     */
    {
      "files": ["*.ts"],
      // ... config specific to TypeScript files
    },

/**
 * -----------------------------------------------------
 * COMPONENT TEMPLATES
 * -----------------------------------------------------
 */
{
  "files": ["*.component.html"],
  // ... config specific to Angular Component templates
},

/**
 * -----------------------------------------------------
 * EXTRACT INLINE TEMPLATES (from within .component.ts)
 * -----------------------------------------------------
 */
{
  "files": ["*.component.ts"],
  // ... applies a special processor to extract the template
  "extends": ["plugin:@angular-eslint/template/process-inline-templates"]
}

] }

By setting up our config in this way, we have complete control over what rules etc apply to what file types and our separate concerns remain clearer and easier to maintain.

For a full reference configuration example check out the full Angular CLI integration test located within this monorepo. Check out the relevant configuration files:

If you are looking for general help in migrating specific rules from TSLint to ESLint, you can check out this project: https://github.com/typescript-eslint/tslint-to-eslint-config


Linting HTML files and inline-templates with the VSCode extension for ESLint

If you use vscode-eslint, and want to lint HTML files and inline-templates on your Angular Components, you will need to make sure you add the following to your VSCode

settings.json
:
// ... more config

"eslint.options": { "extensions": [".ts", ".html"] },

// ... more config

"eslint.validate": [ "javascript", "javascriptreact", "typescript", "typescriptreact", "html" ],

// ... more config

Please see the following issue for more information: https://github.com/microsoft/vscode-eslint/issues/922


Usage without Angular CLI Builder

If you're using this without the Angular CLI Builder don't forget to include

.component.html
as one of the file extensions when running the eslint CLI, otherwise templates will not be linted, e.g.:
eslint --ext .ts,.component.html


Rules List

| | | --------------------------------- | | :whitecheckmark: = done | | :construction: = work in progress |

Functionality

| Codelyzer rule | Status | | ----------------------------------------------- | :----------------: | |

contextual-decorator
| | |
contextual-lifecycle
| :whitecheckmark: | |
no-attribute-decorator
| :whitecheckmark: | |
no-lifecycle-call
| :whitecheckmark: | |
no-output-native
| :whitecheckmark: | |
no-pipe-impure
| :whitecheckmark: | |
prefer-on-push-component-change-detection
| :whitecheckmark: | |
template-accessibility-alt-text
| | |
template-accessibility-elements-content
| | |
template-accessibility-label-for
| | |
template-accessibility-tabindex-no-positive
| :whitecheckmark: | |
template-accessibility-table-scope
| | |
template-accessibility-valid-aria
| | |
template-banana-in-box
| :whitecheckmark: | |
template-click-events-have-key-events
| | |
template-mouse-events-have-key-events
| | |
template-no-any
| | |
template-no-autofocus
| | |
template-no-distracting-elements
| | |
template-no-negated-async
| :whitecheckmark: | |
use-injectable-provided-in
| :whitecheckmark: | |
use-lifecycle-interface
| :whitecheckmark: |

Maintainability

| Codelyzer rule | Status | | ------------------------------------- | :----------------: | |

component-max-inline-declarations
| :whitecheckmark: | |
no-conflicting-lifecycle
| :whitecheckmark: | |
no-forward-ref
| :whitecheckmark: | |
no-input-prefix
| :whitecheckmark: | |
no-input-rename
| :whitecheckmark: | |
no-output-on-prefix
| :whitecheckmark: | |
no-output-rename
| :whitecheckmark: | |
no-unused-css
| | |
prefer-output-readonly
| :whitecheckmark: | |
relative-url-prefix
| :whitecheckmark: | |
template-conditional-complexity
| | |
template-cyclomatic-complexity
| :whitecheckmark: | |
template-i18n
| | |
template-no-call-expression
| :whitecheckmark: | |
template-use-track-by-function
| | |
use-component-selector
| :whitecheckmark: | |
use-component-view-encapsulation
| :whitecheckmark: | |
use-pipe-decorator
| :whitecheckmark: | |
use-pipe-transform-interface
| :whitecheckmark: |

Style

| Codelyzer rule | Status | | -------------------------------- | :----------------: | |

angular-whitespace
| | |
component-class-suffix
| :whitecheckmark: | |
component-selector
| :whitecheckmark: | |
directive-class-suffix
| :whitecheckmark: | |
directive-selector
| :whitecheckmark: | |
import-destructuring-spacing
| | |
no-host-metadata-property
| :whitecheckmark: | |
no-inputs-metadata-property
| :whitecheckmark: | |
no-outputs-metadata-property
| :whitecheckmark: | |
no-queries-metadata-property
| :whitecheckmark: | |
pipe-prefix
| :whitecheckmark: | |
prefer-inline-decorator
| |

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.