Angular eslint: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 184: Line 184:
         createDefaultProgram: true
         createDefaultProgram: true
       },
       },
       extends: [
       extends: [
         "plugin:@angular-eslint/recommended",
         "plugin:jasmine/recommended",
         // AirBnB Styleguide rules
         // AirBnB Styleguide rules
         'airbnb-typescript/base'
         'airbnb-typescript/base'
       ],
       ],    
       rules: {
       rules: {
         // Custom rules
         // Custom rules

Revision as of 04:33, 22 April 2021

Introduction

Just a page to setup Eslint

Install Dependencies

ng add @angular-eslint/schematics

eslintrc.js

In the root of the project create a .eslintrc.js

/**
 * -----------------------------------------------------
 * NOTES ON CONFIGURATION STRUCTURE
 * -----------------------------------------------------
 *
 * Out of the box, ESLint does not support TypeScript or HTML. Naturally those are the two
 * main file types we care about in Angular projects, so we have to do a little extra work
 * to configure ESLint exactly how we need to.
 *
 * Fortunately, ESLint gives us an "overrides" configuration option which allows us to set
 * different lint tooling (parser, plugins, rules etc) for different file types, which is
 * critical because our .ts files require a different parser and different rules to our
 * .html (and our inline Component) templates.
 */
 module.exports = {
  "root": true,
  // Additional projects are linted separately
  "ignorePatterns": ["projects/**/*"],
  "overrides": [
    /**
     * -----------------------------------------------------
     * TYPESCRIPT FILES (COMPONENTS, SERVICES ETC) (.ts)
     * -----------------------------------------------------
     */
    {
      "files": ["*.ts"],
      "parserOptions": {
        "project": [
          "tsconfig.app.json",
          "tsconfig.spec.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/ng-cli-compat",

        /**
         * NOTE:
         *
         * We strongly recommend using a dedicated code formatter, like Prettier, and not
         * using a linter to enforce code formatting concerns.
         *
         * However, for maximum compatibility with how the Angular CLI has traditionally
         * done things using TSLint, this code formatting related add-on config is provided.
         */
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",

        /**
         * -----------------------------------------------------
         * EXTRACT INLINE TEMPLATES (from within Component declarations)
         * -----------------------------------------------------
         *
         * This extra extends is necessary to extract inline templates from within
         * Component metadata, e.g.:
         *
         * @Component({
         *  template: `<h1>Hello, World!</h1>`
         * })
         * ...
         *
         * It works by extracting the template part of the file and treating it as
         * if it were a full .html file, and it will therefore match the configuration
         * specific for *.html above when it comes to actual rules etc.
         *
         * NOTE: This processor will skip a lot of work when it runs if you don't use
         * inline templates in your projects currently, and when it runs on a non-Component
         * file so there is no great benefit in removing it, but you can if you want to.
         */
        "plugin:@angular-eslint/template/process-inline-templates"
      ],
      "rules": {
        /**
         * Any TypeScript related rules you wish to use/reconfigure over and above the
         * recommended set provided by the @angular-eslint project would go here.
         *
         * There are some examples below from the @angular-eslint plugin and ESLint core:
         */
        "@angular-eslint/directive-selector": [
          "error",
          { "type": "attribute", "prefix": "app", "style": "camelCase" }
        ],
        "@angular-eslint/component-selector": [
          "error",
          { "type": "element", "prefix": "app", "style": "kebab-case" }
        ]
      }
    },

    /**
     * -----------------------------------------------------
     * COMPONENT TEMPLATES
     * -----------------------------------------------------
     *
     * If you use inline templates, make sure you you have read the notes on the extends
     * in the "*.ts" overrides above to understand how they relate to this configuration
     * directly below.
     */
    {
      "files": ["*.html"],
      "extends": ["plugin:@angular-eslint/template/recommended"],
      "rules": {
        /**
         * Any template/HTML related rules you wish to use/reconfigure over and above the
         * recommended set provided by the @angular-eslint project would go here.
         *
         * There is an example below from ESLint core (note, this specific example is not
         * necessarily recommended for all projects):
         */
        "max-len": ["error", { "code": 140 }]
      }
    }
  ]
}

Update ng lint command

Edit the angular.json

{
...
        "lint": {
          "builder": "@angular-eslint/builder:lint",
          "options": {
            "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
          }
        },
...
}

Install additional ESLint Plugins

If you want to install another plugin for ESLint, for example, to lint Jasmine spec files, install appropriate npm-package:

npm install eslint-plugin-jasmine --save-dev

We now need to add a section. Each starts with { files: } and is under the overrides section.

overrides: [
  ...,
  {
    files: ['src/**/*.spec.ts', 'src/**/*.d.ts'],
    parserOptions: {
      project: './src/tsconfig.spec.json',
    },
    // Jasmine rules
    extends: ['plugin:jasmine/recommended'],
    // Plugin to run Jasmine rules
    plugins: ['jasmine'],
    env: { jasmine: true },
    // Turn off 'no-unused-vars' rule
    rules: {
      '@typescript-eslint/no-unused-vars': 'off'
    }
  }
],

Install airbnb

Install the style guide

npm install eslint-plugin-import eslint-config-airbnb-typescript --save-dev

As with the jasmine plugin add the *.ts entry under overrides

module.exports = {
  ...,
  overrides: [
    {
      files: ["*.ts"],
      parserOptions: {
        project: [
          "tsconfig.*?.json",
          "e2e/tsconfig.json"
        ],
        createDefaultProgram: true
      },

      extends: [
        "plugin:jasmine/recommended",
        // AirBnB Styleguide rules
        'airbnb-typescript/base'
      ],      
      rules: {
        // Custom rules
        'import/no-unresolved': 'off',
        'import/prefer-default-export': 'off',
        'class-methods-use-this': 'off',
        'lines-between-class-members': 'off',
        '@typescript-eslint/unbound-method': [
          'error',
          {
            ignoreStatic: true,
          }
        ]
      }
    },
    ...
  ]
}

Configuring Prettier

To add Prettier in ESLint config, we need to install Prettier itself, plugin with Prettier rules and config that turns off all rules that conflict with Prettier:

npm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev

In ESLint config "overrides" in the bottom of "extends" property in the block of rules for files with .ts extension add Prettier settings:

module.exports = {
  ...,
  overrides: [
    {
      files: ["*.ts"],
      parserOptions: {
        project: [
          "tsconfig.*?.json",
          "e2e/tsconfig.json"
        ],
        createDefaultProgram: true
      },
      extends: [
        "plugin:@angular-eslint/recommended",
        // AirBnB Styleguide rules,
        'airbnb-typescript/base',
        // Settings for Prettier
        'prettier/@typescript-eslint',
        'plugin:prettier/recommended'
      ],
      rules: {
        ...
      }
    },
    ...
  ]
}

Configuration for Prettier should always be in the bottom of "extends" property, to turn off all the previous rules, which can conflict with Prettier.

prettier/@typescript-eslint turns off rules from @typescript-eslint, which can conflict with Prettier, and plugin:prettier/recommended does three things:

  • enables eslint-plugin-prettier,
  • marks prettier/prettier rules as "error",
  • adds Prettier formatting rules eslint-config-prettier.

Prettier configuration

Prettier can format files with no configuration but for AirBnB code guide we need to specify some settings. Create .prettierrc.js in app root folder:

module.exports = {
  trailingComma: "all",
  tabWidth: 2,
  semi: true,
  singleQuote: true,
  bracketSpacing: true,
  printWidth: 100
};

This configuration will be used by ESLint and by Prettier if you want to run it separately. You can format your code with Prettier itself with prettier --write . or with Prettier Plugin for VS Code.

Configuring VS Code

VS Code can highlight errors which are found by ESLint and fix them on file save. To enable this feature install ESLint plugin for VS Code and create a file with configuration for workspace .vscode/settings.json:

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

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

  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
  },

You can also install Prettier plugin for VS Code to format files with shift + option + f with Prettier.

Configuring Git Hooks

Git Hooks are scripts, which Git calls on certain events: commit, push, receive.

With Hooks we can run linting on commit creation to reduce errors falls into pull requests. For better work with Git Hooks install Husky, and to lint only staged files (it is necessary on big projects where linting can be very long) lint-staged:

npm i husky lint-staged --save-dev

Add new settings for this plugins in package.json:

"scripts": {
  ...,
},
"husky": {
  "hooks": {
    "pre-commit": "lint-staged --relative"
  }
},
"lint-staged": {
  "*.{js,ts}": [
     "eslint --fix"
  ]
},

Lint-staged sends to the called command array of staged files. ng lint can't accept arrays of files and to use it we have to write an additional handler script. Or we can just run ESLint like in this example. You can use this solution for precommits, and ng lint for linting all files of project, for example, in CI pipeline.