How do I lint .html files of my Angular Project using ESLint in my VSCode

1.3k Views Asked by At

ESLint is already installed in my Angular project and linting all the typescript files. I have also written some set of rules for typescript files to display warnings instead of errors. But the rules I wrote for html didn't work. I am not able to lint my html files

eslintrc.json

{
  "root": true,
  "ignorePatterns": ["projects/**/*"],
  "overrides": [
    {
      "files": ["*.ts"],
      "parserOptions": {
        "project": ["tsconfig.json", "e2e/tsconfig.json"],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/ng-cli-compat",
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
        "plugin:@angular-eslint/template/process-inline-templates"
      ],
      "rules": {
        "@angular-eslint/component-selector": [
          "error",
          {
            "type": "element",
            "prefix": "app",
            "style": "kebab-case"
          }
        ],
        "@angular-eslint/directive-selector": [
          "error",
          {
            "type": "attribute",
            "prefix": "app",
            "style": "camelCase"
          }
        ],
        "@typescript-eslint/consistent-type-definitions": "error",
        "@typescript-eslint/dot-notation": "off",
        "@typescript-eslint/explicit-member-accessibility": [
          "off",
          {
            "accessibility": "explicit"
          }
        ],
        "@typescript-eslint/no-use-before-define": "error",
        "brace-style": ["warn", "1tbs"],
        "id-blacklist": "off",
        "id-match": "off",
        "max-len": "off",
        "no-underscore-dangle": "off",
        "valid-typeof": "error",
        "@typescript-eslint/member-ordering": "warn",
        "@typescript-eslint/consistent-type-assertions": "warn",
        "@typescript-eslint/type-annotation-spacing": "warn",
        "@typescript-eslint/naming-convention": "warn",
        "@typescript-eslint/quotes": "warn",
        "@typescript-eslint/no-inferrable-types": "warn",
        "@typescript-eslint/semi": "warn",
        "@typescript-eslint/member-delimiter-style": "off",
        "@typescript-eslint/no-unused-expressions": "warn",
        "arrow-body-style": "warn",
        "arrow-spacing": "warn",
        "curly": "warn",
        "eqeqeq": "warn",
        "indent": ["warn", 2],
        "max-line-length": "off",
        "member-access": "off",
        "no-bitwise": "warn",
        "no-console": [
          "warn",
          { "allow": ["info", "warn", "error", "time", "timeEnd", "trace"] }
        ],
        "no-debugger": "warn",
        "no-empty": "off",
        "no-eval": "warn",
        "no-shadow": "warn",
        "no-string-literal": "off",
        "no-trailing-spaces": "warn",
        "no-var": "warn",
        "object-literal-sort-keys": "off",
        "prefer-const": "warn",
        "quote-props": "warn",
        "radix": "warn",
        "space-before-blocks": "warn",
        "space-infix-ops": "warn",
        "space-in-parens": "warn",
        "no-multi-spaces": "warn",
        "comma-dangle": "warn",
        "default-case": "warn",
        "eol-last": "warn",
        "guard-for-in": "warn",
        "key-spacing": "warn",
        "keyword-spacing": "warn",
        "no-extra-parens": "warn",
        "no-extra-semi": "warn",
        "no-multiple-empty-lines": "warn",
        "no-unused-expressions": "warn",
        "variable-name": "off"
      }
    },
    {
      "files": ["*.html"],
      "extends": ["plugin:@angular-eslint/template/recommended"],
      "rules": {
        "eqeqeq": "warn",
        "indent": ["warn", 2],
      }
    }
  ]
}

package.json

{
  "name": "cat",
  "version": "1.0.1",
  "license": "MIT",
  "scripts": {
    "build-high": "node --max_old_space_size=7000 ./node_modules/@angular/cli/bin/ng build --prod --output-hashing=all",
    "ng": "ng",
    "start": "ng serve --host 0.0.0.0",
    "serve": "set NODE_OPTIONS=--max_old_space_size=8192 & ng serve --open",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "build-prod": "node ./replace.build.js && ng build --prod --aot=false",
    "bundle-analyze": "node --max_old_space_size=7000 ./node_modules/@angular/cli/bin/ng build --prod --stats-json && webpack-bundle-analyzer dist/stats-es2015.json"
  },
  "private": true,
  "dependencies": {
    "@agm/core": "^1.1.0",
    "@amcharts/amcharts3-angular": "^2.2.4",
    "@amcharts/amcharts4": "^4.10.21",
    "@angular/animations": "^8.2.0",
    "@angular/common": "^8.2.0",
    "@angular/compiler": "^8.2.0",
    "@angular/core": "^8.2.0",
    "@angular/forms": "^8.2.0",
    "@angular/platform-browser": "^8.2.0",
    "@angular/platform-browser-dynamic": "^8.2.0",
    "@angular/router": "^8.2.0",
    "@angular/service-worker": "^8.2.0",
    "@types/lodash": "^4.14.104",
    "ag-grid-angular": "^25.2.0",
    "ag-grid-community": "^25.2.0",
    "angular-font-awesome": "^3.0.3",
    "angular2-counto": "^1.2.5",
    "angular2-text-mask": "^8.0.4",
    "angular2-tinymce": "^2.1.2",
    "auth0-js": "^9.15.0",
    "auth0-lock": "^11.29.0",
    "d3": "^4.12.2",
    "d3-scale-chromatic": "^1.3.3",
    "dom-autoscroller": "^2.3.4",
    "file-saver": "^2.0.5",
    "font-awesome": "^4.7.0",
    "html2canvas": "^1.0.0-rc.7",
    "jspdf": "^2.3.1",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "ng2-dragula": "^2.1.1",
    "ng2-pdf-viewer": "^6.4.1",
    "radial-progress-chart": "0.0.4",
    "rxjs": "^6.6.7",
    "rxjs-compat": "^6.6.7",
    "signalr-no-jquery": "^0.2.0",
    "tslib": "^2.2.0",
    "underscore.deepclone": "^0.1.3",
    "webpack-bundle-analyzer": "^3.9.0",
    "xlsx": "^0.16.9",
    "zone.js": "^0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^0.803.20",
    "@angular-eslint/builder": "1.2.0",
    "@angular-eslint/eslint-plugin": "1.2.0",
    "@angular-eslint/eslint-plugin-template": "1.2.0",
    "@angular-eslint/schematics": "1.2.0",
    "@angular-eslint/template-parser": "1.2.0",
    "@angular/cdk": "^8.2.3",
    "@angular/cli": "^8.2.0",
    "@angular/compiler-cli": "^8.2.0",
    "@angular/language-service": "^8.2.0",
    "@types/googlemaps": "^3.43.3",
    "@types/jasmine": "^3.7.0",
    "@types/jasminewd2": "^2.0.9",
    "@types/node": "^15.0.2",
    "@typescript-eslint/eslint-plugin": "4.3.0",
    "@typescript-eslint/parser": "4.3.0",
    "codelyzer": "^6.0.1",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsdoc": "30.7.6",
    "eslint-plugin-prefer-arrow": "1.2.2",
    "jasmine-core": "^3.7.1",
    "jasmine-spec-reporter": "^7.0.0",
    "karma": "^6.3.2",
    "karma-chrome-launcher": "^3.1.0",
    "karma-cli": "^2.0.0",
    "karma-coverage-istanbul-reporter": "^3.0.3",
    "karma-jasmine": "^4.0.1",
    "karma-jasmine-html-reporter": "^1.6.0",
    "protractor": "^7.0.0",
    "replace-in-file": "^6.2.0",
    "ts-node": "^9.1.1",
    "typescript": "^3.5.3",
    "webpack": "^4.46.0"
  }
}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "cat": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist",
            "index": "src/index.html",
            "main": "src/main.ts",
            "tsConfig": "src/tsconfig.app.json",
            "polyfills": "src/polyfills.ts",
            "assets": [
              "src/assets",
              "src/favicon.ico",
              "src/Web.config"
            ],
            "styles": [
              "src/styles.scss",
              "node_modules/font-awesome/scss/font-awesome.scss",
              "node_modules/ag-grid-community/dist/styles/ag-grid.css",
              "node_modules/ag-grid-community/dist/styles/ag-theme-balham.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "serviceWorker": true,
              "ngswConfigPath": "src/ngsw-config.json",
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "cat:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "cat:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "cat:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "karmaConfig": "./karma.conf.js",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "scripts": [],
            "styles": [
              "src/styles.scss",
              "node_modules/font-awesome/scss/font-awesome.scss",
              "node_modules/ag-grid-community/dist/styles/ag-grid.css",
              "node_modules/ag-grid-community/dist/styles/ag-theme-balham.css"
            ],
            "assets": [
              "src/assets",
              "src/favicon.ico",
              "src/Web.config"
            ]
          }
        },
        "lint": {
          "builder": "@angular-eslint/builder:lint",
          "options": {
            "lintFilePatterns": [
              "src/**/*.ts",
              "src/**/*.html"
            ]
          }
        }
      }
    },
    "cat-e2e": {
      "root": "e2e",
      "sourceRoot": "e2e",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "./protractor.conf.js",
            "devServerTarget": "cat:serve"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "e2e/tsconfig.e2e.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "cat",
  "schematics": {
    "@schematics/angular:component": {
      "prefix": "app",
      "styleext": "scss"
    },
    "@schematics/angular:directive": {
      "prefix": "app"
    }
  }
}

I tried writing rules for html files. You can find 2 rules, "eqeqeq" and "indent" at the bottom of my eslintre.json file. And my expectations were that it would start linting html files just like I it is linting all typescript files of my project.

1

There are 1 best solutions below

0
On

You are trying to apply rules which are designed to run on JavaScript code on your Angular templates. This does not work, the rules understand JavaScript syntax but don't understand Angular's template syntax.

For the eqeqeq rule, luckily the Angular ESLint template plugin contains an equivalent rule @angular-eslint/template/eqeqeq. You can set up the rule like the following:

{
  "overrides": [
    {
      "files": ["*.html"],
      "extends": ["plugin:@angular-eslint/template/recommended"],
      "rules": {
        "@angular-eslint/template/eqeqeq": "warn"
      }
    }
  ]
}

For the indent rule there is no equivalent rule in Angular ESLint. They will never add such rule, because it's formatting related and they decided to stop implementation of formatting related rules. You would need to implement a custom ESLint rule. For easier implementation you can use Angular ESLint's template parser.