lint-staged is not taking .eslintrc.js configuration.

Created on 31 Jul 2019  路  7Comments  路  Source: okonet/lint-staged

[BUG]

Description

I have created 2 package.json npm scripts:

     "lint-staged:test": "lint-staged",
     "eslint:test": "eslint --fix src/global/AppRouter/AppRouter.tsx",

My configuration for lint-staged looks like;

"lint-staged": {
    "*.tsx": [
      "eslint --fix",
      "git add"
    ]
  }

By running yarn eslint:test or npm run eslint:test I've got no errors.
Like on the image attached:
image

But by running second command ("lint-staged:test") I've got some errors related with the file that was checked with the first command. Image shows it:
image

Those are my rules for eslint (.eslinrc.js file):

module.exports = {
  parser: '@typescript-eslint/parser', // Specifies the ESLint parser
  extends: ['plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'plugin:prettier/recommended'],
  parserOptions: {
    ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
    sourceType: 'module', // Allows for the use of imports
    ecmaFeatures: {
      jsx: true, // Allows for the parsing of JSX
    },
  },
  rules: {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",

    // note you must disable the base rule as it can report incorrect errors
    indent: 'off',
    '@typescript-eslint/indent': ['error', 2],
  },
  settings: {
    react: {
      version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
    },
  },
};

which are applied for the first command but are not applied for lint-staged.

Some possible solutions?

Environment

  • OS: Windows 10,
  • Node.js: v10.13.0,
  • lint-staged: 9.2.1,
  • eslint: 5.3.0",

Most helpful comment

@husseinbob yeah, lint-staged will hide unstaged changes before running tasks, so at that point eslint would see the old version of your config.

All 7 comments

In your eslint config you have specified this rule '@typescript-eslint/indent': ['error', 2],. When _lint-staged_ runs, it is showing errors related to this rule. To me this seems correct.

I think your issue is the other way around: your plain _eslint_ command is not picking up the configuration.

Eslint errors show it wants 4 spaces instead of 2.

This rule says I want 2 spaces:
'@typescript-eslint/indent': ['error', 2],
And I have got them.

Eslint error says "Expected indentation of 4 spaces but found 2".

So eslint is using this rule:
'@typescript-eslint/indent': ['error', 4],

Anyway, I have solved this problem with:

  • changing .eslinrc.js file to JSON format instead of .js it is .eslintrc.json
  • commit with --no-verify flag (it looks like lint-staged messed up with some of my files or my IDE showed me them incorrectly - JetBrains WebStorm)

Anyway x2, solved.

I'm currently having the same problem, where the cli output from lint-staged is different to eslint. I'm using eslintrc.js but if i rename to .json and remove the module.exports I instead get another error about "m at position 0"

@husseinbob Please post your debug logs, otherwise nothing can be done.

I think I found the issue. my changes to .eslintrc.js also needed to be staged, by the looks of it? either way, git adding the eslintrc file stopped the error.

@husseinbob yeah, lint-staged will hide unstaged changes before running tasks, so at that point eslint would see the old version of your config.

I confirm that it's not working when I run lint-staged whereas running eslint directly works fine - it's complaining about no parser found, because i'm running it on .HTML files, and there is no default parser configured.

C:\dev\file-upload.component.html 0:0 error Parsing error: Template parse errors: Parser Error: Unexpected token '=' at column 13 in [(locationId)=$event] in C:
[long errors list]

.eslintrc.js config

module.exports = {
    "env": {
        "browser": true,
        "es6": true,
        "node": true
    },
    "overrides": [
        {
            "files": ["*.ts"],
            extends: [
                "plugin:@angular-eslint/recommended", // Rules specific to angular
                "eslint:recommended", // The set of rules which are recommended for all projects by the ESLint Team
                "plugin:@typescript-eslint/eslint-recommended", // As noted in the root README, not all ESLint core rules are compatible with TypeScript, so you need to add both eslint:recommended and plugin:@typescript-eslint/eslint-recommended (which will adjust the one from ESLint appropriately for TypeScript) to your config
                "plugin:@typescript-eslint/recommended" // Uses the recommended rules from the @typescript-eslint/eslint-plugin
            ],
            "parser": "@typescript-eslint/parser",
            "parserOptions": {
                "ecmaVersion": 2020, // Allows for the parsing of modern ECMAScript features
                "project": "./tsconfig.json",
                "sourceType": "module"
            },
            "plugins": [
                "import",
                "@angular-eslint",
                "@typescript-eslint"
            ],
            "rules": {
                "@angular-eslint/component-class-suffix": "error",
                "@angular-eslint/contextual-lifecycle": "error",
                "@angular-eslint/directive-class-suffix": "error",
                "@angular-eslint/no-host-metadata-property": "error",
                "@angular-eslint/no-input-rename": "error",
                "@angular-eslint/no-inputs-metadata-property": "error",
                "@angular-eslint/no-output-on-prefix": "error",
                "@angular-eslint/no-output-rename": "error",
                "@angular-eslint/no-outputs-metadata-property": "error",
                "@angular-eslint/use-component-view-encapsulation": "error",
                "@angular-eslint/use-lifecycle-interface": "error",
                "@angular-eslint/use-pipe-decorator": "error",
                "@angular-eslint/use-pipe-transform-interface": "error",
                "@typescript-eslint/naming-convention": [
                    "error",
                    {
                        "selector": "variableLike", // matches the same as `variable`, `function` and `parameter`
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "(([a-z][a-z0-9]+)((d)|([A-Z0-9][a-z0-9]+))*([A-Z])?)|(^[A-Z]+(?:_[A-Z]+)*$)|([a-z])", // this checks for camelCaseVars that allow multiple humps i.e. capitals in the middle, but not consecutively, for UPPER_CASE_VARS, and also a single a-z lowercase var
                            "match": true
                        }
                    },
                    {
                        "selector": "memberLike",
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "(([a-z][a-z0-9]+)((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?)|^(\\d*|\\D*)$", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively, and also any set of numbers only (22334455) or any set of letters only (abcdef) but not alphanumeric (mixed123Like567This)
                            "match": true
                        }
                    },
                    {
                        "selector": "memberLike",
                        "modifiers": ["private"],
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "([a-z][a-z0-9]+)((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively.
                            "match": true
                        },
                        "leadingUnderscore": "allow"
                    },
                    {
                        "selector": "enumMember",
                        "format": ["PascalCase"]
                    },
                    {
                        "selector": "variable",
                        "types": ["boolean"],
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "([a-z][a-z0-9]+)?((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively.
                            "match": true
                        },
                        "prefix": ["is", "should", "has", "can", "did", "will"]
                    },
                    {
                        "selector": "typeParameter",
                        "format": ["PascalCase"],
                        "prefix": ["T"]
                    }, {
                        "selector": "class",
                        "format": ["PascalCase"]
                    },
                    {
                        "selector": "typeLike",
                        "format": ["PascalCase"]
                    }
                ],
                "@typescript-eslint/consistent-type-definitions": "error",
                "@typescript-eslint/dot-notation": "off",
                "@typescript-eslint/explicit-function-return-type": [
                    "error",
                    {
                        "allowExpressions": true
                    }
                ],
                "@typescript-eslint/explicit-member-accessibility": [
                    "off",
                    {
                        "accessibility": "explicit"
                    }
                ],
                "@typescript-eslint/indent": [
                    "error", 4,
                    { SwitchCase: 1 }
                ],
                "@typescript-eslint/member-delimiter-style": [
                    "error",
                    {
                        "multiline": {
                            "delimiter": "semi",
                            "requireLast": true
                        },
                        "singleline": {
                            "delimiter": "semi",
                            "requireLast": false
                        }
                    }
                ],
                "@typescript-eslint/member-ordering": "error",
                "@typescript-eslint/no-empty-function": "off",
                "@typescript-eslint/no-empty-interface": "error",
                "@typescript-eslint/no-explicit-any": 0,
                "@typescript-eslint/no-inferrable-types": "error",
                "@typescript-eslint/no-misused-new": "error",
                "@typescript-eslint/no-non-null-assertion": "error",
                "@typescript-eslint/no-unused-expressions": "error",
                "@typescript-eslint/no-use-before-define": "error",
                "@typescript-eslint/prefer-function-type": "error",
                "@typescript-eslint/explicit-module-boundary-types": 0,
                "@typescript-eslint/quotes": [
                    "error",
                    "single"
                ],
                "@typescript-eslint/semi": [
                    "error",
                    "always"
                ],
                "@typescript-eslint/type-annotation-spacing": "error",
                "@typescript-eslint/unified-signatures": "error",
                "arrow-body-style": "error",
                "brace-style": [
                    "error",
                    "1tbs"
                ],
                "camelcase": "off",
                "constructor-super": "error",
                "curly": "error",
                "eol-last": "error",
                "eqeqeq": [
                    "error",
                    "smart"
                ],
                "guard-for-in": "error",
                "id-blacklist": "off",
                "id-match": "off",
                "import/no-deprecated": "warn",
                "key-spacing": [
                    "error",
                    {
                        'singleLine': {
                            'beforeColon': false,
                            'afterColon': true
                        },
                        "align": {
                            "beforeColon": false,
                            "afterColon": true,
                            "on": "value"
                        }
                    }],
                "lines-between-class-members": ["error", "always", { exceptAfterSingleLine: true }],
                "max-classes-per-file": [
                    "error",
                    2
                ],
                "max-len": [
                    "error",
                    {
                        "ignoreComments": true,
                        "ignoreUrls": true,
                        "ignoreStrings": true,
                        "ignoreRegExpLiterals": true,
                        "ignoreTemplateLiterals": true,
                        "code": 180
                    }
                ],
                "no-bitwise": "error",
                "no-caller": "error",
                "no-console": process.env.NODE_ENV === "production" ? ["error", { allow: ["warn", "error"] }] : "off",
                "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
                "no-empty": "off",
                "no-eval": "error",
                "no-fallthrough": "error",
                "no-new-wrappers": "error",
                "no-restricted-imports": [
                    "error",
                    "rxjs/Rx"
                ],
                "no-restricted-syntax": 0,
                "no-shadow": [
                    "error",
                    {
                        "hoist": "all"
                    }
                ],
                "no-throw-literal": "error",
                "no-trailing-spaces": "error",
                "no-undef-init": "error",
                "no-underscore-dangle": "off",
                "no-unused-labels": "error",
                "no-var": "error",
                "padded-blocks": ["error", "never"],
                "prefer-const": "error",
                "radix": "error",
                "keyword-spacing": [
                    2, {
                        "before": true,
                        "after": true,
                        "overrides": {}
                    }],
                "spaced-comment": [
                    "error",
                    "always",
                    {
                        "markers": [
                            "/"
                        ]
                    }
                ],
                "@angular-eslint/directive-selector": [
                    "error",
                    {
                        "type": "attribute",
                        "prefix": "app",
                        "style": "camelCase"
                    }
                ],
                "@angular-eslint/component-selector": [
                    "error",
                    {
                        "type": "element",
                        "prefix": "app",
                        "style": "kebab-case"
                    }
                ]
            }
        },
        {
            files: ["*.component.html"],
            parser: "@angular-eslint/template-parser",
            plugins: ["@angular-eslint/template"],
            rules: {
                "@angular-eslint/template/banana-in-a-box": "error",
                "@angular-eslint/template/no-negated-async": "error"
            }
        }
    ]
};

package.json

scripts: {
       // this works
        "lint": "cross-env TIMING=1 eslint '**/*.{ts,component.html}' --ignore-pattern '*.d.ts' --fix",
    },
    "lint-staged": {
        "*.{ts,component.html}": "eslint --cache --fix", // this doesn't work
        "*.html": "prettier --write"
    }

UPDATE:

I found out that running eslint --debug shows that both eslint and lint-staged do in fact load the config. See output

2020-05-26T21:31:35.496Z eslint:config-array-factory Config file found: C:\dev\.eslintrc.js

So it isn't due to not loading the config, at least not on initial pass. It's something with the way eslint is parsing it during the --fix flag.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tnrich picture tnrich  路  7Comments

okonet picture okonet  路  5Comments

okcoker picture okcoker  路  4Comments

thedamon picture thedamon  路  3Comments

okonet picture okonet  路  6Comments