UNPKG

eslint-config-angular-strict

Version:

Modern ESLint configuration with strict rules for Angular development.

188 lines (177 loc) 9.29 kB
import angularEslintPlugin from '@angular-eslint/eslint-plugin'; import angularTemplateParser from '@angular-eslint/template-parser'; import angularTemplatePlugin from '@angular-eslint/eslint-plugin-template'; import importXPlugin from 'eslint-plugin-import-x'; import stylistic from '@stylistic/eslint-plugin'; import tsEslintParser from '@typescript-eslint/parser'; import tsEslintPlugin from '@typescript-eslint/eslint-plugin'; import unicornPlugin from 'eslint-plugin-unicorn'; import { configs, rules } from 'eslint-config-airbnb-extended'; export default [ { ignores: ['dist/**', 'node_modules/**'], plugins: { '@angular-eslint/template': angularTemplatePlugin, '@stylistic': stylistic, '@typescript-eslint': tsEslintPlugin, 'import-x': importXPlugin, }, }, ...configs.base.all, unicornPlugin.configs.all, rules.base.importsStrict, rules.typescript.typescriptEslintStrict, // TypeScript files configuration { files: ['**/*.ts'], languageOptions: { parser: tsEslintParser }, plugins: { '@angular-eslint': angularEslintPlugin }, rules: { // Angular ESLint rules '@angular-eslint/component-class-suffix': ['error', { suffixes: ['Component', 'Modal', 'Page'] }], '@angular-eslint/component-max-inline-declarations': 'error', '@angular-eslint/consistent-component-styles': 'error', '@angular-eslint/contextual-decorator': 'error', '@angular-eslint/contextual-lifecycle': 'error', '@angular-eslint/directive-class-suffix': 'error', '@angular-eslint/no-async-lifecycle-method': 'error', '@angular-eslint/no-attribute-decorator': 'error', '@angular-eslint/no-duplicates-in-metadata-arrays': 'error', '@angular-eslint/no-empty-lifecycle-method': 'error', '@angular-eslint/no-forward-ref': 'error', '@angular-eslint/no-input-prefix': ['error', { prefixes: ['on'] }], '@angular-eslint/no-input-rename': 'error', '@angular-eslint/no-inputs-metadata-property': 'error', '@angular-eslint/no-lifecycle-call': 'error', '@angular-eslint/no-output-native': 'error', '@angular-eslint/no-output-on-prefix': 'error', '@angular-eslint/no-output-rename': 'error', '@angular-eslint/no-outputs-metadata-property': 'error', '@angular-eslint/no-pipe-impure': 'error', '@angular-eslint/no-queries-metadata-property': 'error', '@angular-eslint/no-uncalled-signals': 'error', '@angular-eslint/prefer-host-metadata-property': 'error', '@angular-eslint/prefer-output-readonly': 'error', '@angular-eslint/prefer-standalone': 'error', '@angular-eslint/relative-url-prefix': 'error', '@angular-eslint/require-lifecycle-on-prototype': 'error', '@angular-eslint/sort-lifecycle-methods': 'error', '@angular-eslint/use-component-view-encapsulation': 'error', '@angular-eslint/use-injectable-provided-in': 'error', '@angular-eslint/use-lifecycle-interface': 'error', '@angular-eslint/use-pipe-transform-interface': 'error', // ESLint rules 'class-methods-use-this': 'off', 'complexity': ['error', { max: 25 }], 'max-lines': ['error', { max: 400, skipBlankLines: true, skipComments: true }], 'no-fallthrough': 'off', 'no-param-reassign': ['error', { props: false }], 'no-plusplus': 'off', 'no-return-assign': 'off', 'no-underscore-dangle': ['error', { allowAfterThis: true }], 'radix': ['error', 'as-needed'], 'sort-keys': ['error', 'asc', { allowLineSeparatedGroups: true, natural: true }], // Import rules 'import-x/no-anonymous-default-export': 'error', 'import-x/no-commonjs': 'error', 'import-x/no-cycle': ['error', { maxDepth: 2 }], 'import-x/no-deprecated': 'error', 'import-x/no-import-module-exports': 'off', 'import-x/order': [ 'error', { alphabetize: { order: 'asc', caseInsensitive: true }, named: true, 'newlines-between': 'always', pathGroups: [ { pattern: '@angular/**', group: 'external', position: 'before' }, { pattern: '@nestjs/**', group: 'external', position: 'before' }, { pattern: 'firebase*/**', group: 'external', position: 'before', patternOptions: { partial: true } }, { pattern: 'ng-zorro-antd/**', group: 'external', position: 'before' }, ], pathGroupsExcludedImportTypes: [], warnOnUnassignedImports: true, }, ], 'import-x/prefer-default-export': 'off', // Stylistic rules '@stylistic/arrow-parens': ['error', 'as-needed', { requireForBlockBody: true }], '@stylistic/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], '@stylistic/max-len': ['error', { code: 165, tabWidth: 2 }], '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 5 }], '@stylistic/object-curly-newline': [ 'error', { ExportDeclaration: { consistent: true, minProperties: 10, multiline: true }, ImportDeclaration: { consistent: true, minProperties: 10, multiline: true }, ObjectExpression: { consistent: true, minProperties: 4, multiline: true }, ObjectPattern: { consistent: true, minProperties: 4, multiline: true }, TSEnumBody: { consistent: true, minProperties: 4, multiline: true }, TSInterfaceBody: { consistent: true, minProperties: 4, multiline: true }, TSTypeLiteral: { consistent: true, minProperties: 4, multiline: true }, }, ], '@stylistic/padded-blocks': ['error', { blocks: 'never', classes: 'always', switches: 'never' }], // TypeScript ESLint rules '@typescript-eslint/consistent-type-assertions': ['error', { arrayLiteralTypeAssertions: 'never', assertionStyle: 'as', objectLiteralTypeAssertions: 'never' }], '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'no-type-imports' }], '@typescript-eslint/member-ordering': 'error', '@typescript-eslint/no-extraneous-class': ['error', { allowEmpty: true, allowStaticOnly: true }], '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-unnecessary-type-conversion': 'error', '@typescript-eslint/promise-function-async': ['error', { checkArrowFunctions: false }], '@typescript-eslint/sort-type-constituents': 'error', '@typescript-eslint/unbound-method': ['error', { ignoreStatic: true }], // Unicorn rules 'unicorn/consistent-function-scoping': ['error', { checkArrowFunctions: false }], 'unicorn/new-for-builtins': 'off', 'unicorn/no-abusive-eslint-disable': 'off', 'unicorn/no-array-for-each': 'off', 'unicorn/no-null': 'off', 'unicorn/no-useless-promise-resolve-reject': 'off', 'unicorn/prefer-top-level-await': 'off', 'unicorn/switch-case-braces': ['error', 'avoid'], }, }, // HTML Template files configuration { files: ['**/*.html'], languageOptions: { parser: angularTemplateParser }, rules: { // Angular ESLint rules '@angular-eslint/template/attributes-order': ['error', { alphabetical: true }], '@angular-eslint/template/banana-in-box': 'error', '@angular-eslint/template/conditional-complexity': 'error', '@angular-eslint/template/cyclomatic-complexity': ['error', { maxComplexity: 10 }], '@angular-eslint/template/elements-content': 'error', '@angular-eslint/template/eqeqeq': 'error', '@angular-eslint/template/label-has-associated-control': 'error', '@angular-eslint/template/mouse-events-have-key-events': 'error', '@angular-eslint/template/no-any': 'error', '@angular-eslint/template/no-autofocus': 'error', '@angular-eslint/template/no-call-expression': 'error', '@angular-eslint/template/no-distracting-elements': 'error', '@angular-eslint/template/no-duplicate-attributes': 'error', '@angular-eslint/template/no-empty-control-flow': 'error', '@angular-eslint/template/no-interpolation-in-attributes': 'error', '@angular-eslint/template/no-negated-async': 'error', '@angular-eslint/template/no-nested-tags': 'error', '@angular-eslint/template/no-positive-tabindex': 'error', '@angular-eslint/template/prefer-at-else': 'error', '@angular-eslint/template/prefer-at-empty': 'error', '@angular-eslint/template/prefer-built-in-pipes': 'error', '@angular-eslint/template/prefer-contextual-for-variables': 'error', '@angular-eslint/template/prefer-control-flow': 'error', '@angular-eslint/template/prefer-self-closing-tags': 'error', '@angular-eslint/template/prefer-static-string-properties': 'error', '@angular-eslint/template/prefer-template-literal': 'error', '@angular-eslint/template/role-has-required-aria': 'error', '@angular-eslint/template/table-scope': 'error', '@angular-eslint/template/use-track-by-function': ['error', { alias: ['ngForTrackByIndex', 'ngForTrackByProperty'] }], '@angular-eslint/template/valid-aria': 'error', // Unicorn rules 'unicorn/prefer-string-raw': 'off', 'unicorn/template-indent': 'off', }, }, ];