Run global ESLint with plugin eslint-plugin-jsx-a11y
Asked Answered
R

1

8

I'm trying to run a global installation of ESLint against a single file, using a specified path to the configuration file:

eslint FileToCheck.jsx --config "../path/to/config/.eslintrc.js"

but I'm getting the error

ESLint couldn't find the plugin "eslint-plugin-jsx-a11y". This can happen for a couple different reasons:

  1. If ESLint is installed globally, then make sure eslint-plugin-jsx-a11y is also installed globally. A globally-installed ESLint cannot find a locally-installed plugin.

  2. If ESLint is installed locally, then it's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

    npm i eslint-plugin-jsx-a11y@latest --save-dev

So it seems like #1 is applicable and I need to install eslint-plugin-jsx-a11y globally. I try to do this with

yarn global add eslint-plugin-jsx-a11y

and rerun the original ESLint command, but it fails with the same error. I noticed during the yarn global add that some of the output said

"[email protected]" has no binaries

Indeed, when I check ~/AppData/Local/Yarn/bin I do not find any binaries for that plugin (though I do for ESLint).

How can I make ESLint run globally with this plugin? A good answer will not tell me just to install it locally, but will actually answer the question given - how this can be accomplished with globally installed ESLint and plugins.

Packages I have installed globally with yarn:

  • eslint
  • babel-core
  • babel-eslint
  • eslint-plugin-import
  • eslint-plugin-react
  • eslint-plugin-jsx-a11y
  • eslint-config-airbnb

Here is my .eslintrc.js, which may or may not be relevant:

module.exports = {
  'extends': 'airbnb',
  'plugins': [
    'react',
    'jsx-a11y',
    'import'
  ],

  'env': {
    'browser': true
  },

  'parser': 'babel-eslint',

  'rules': {
    'prefer-template': 'error',
    'comma-dangle': ['error', 'always-multiline'],
    'import/no-extraneous-dependencies': 'off',
    'react/prop-types': 'off',
    'react/jsx-no-bind': 'off',
    'jsx-a11y/no-static-element-interactions': 'off',
    'jsx-a11y/no-noninteractive-element-interactions': 'off',
    'jsx-a11y/alt-text': 'off',
    'jsx-a11y/no-autofocus': 'off',
    'eqeqeq': ['error', 'always', { 'null': 'ignore' }],
    'no-use-before-define': ['error', { 'functions': false }],
    'func-style': ['error', 'declaration', { 'allowArrowFunctions': true }],
    'no-console': 'off',
    'no-alert': 'off',
    'no-continue': 'off',
    'no-param-reassign': ['error', { 'props': false }],
    'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }],
    'one-var-declaration-per-line': ['error', 'initializations'],
    'one-var': 'off', // Not needed because of one-var-declaration-per-line
    'indent': ['error', 2, {
      'FunctionDeclaration': { 'parameters': 'first' },
      'SwitchCase': 1
    }],
    'no-restricted-syntax': [
      'error',
      {
        selector: 'ForInStatement',
        message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
      },
      {
        selector: 'LabeledStatement',
        message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
      },
      {
        selector: 'WithStatement',
        message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
      },
    ],
  }
};

if (process.env.FEATURE_FLAGS) {
  const flags = Object.keys(JSON.parse(process.env.FEATURE_FLAGS));

  module.exports.globals = flags.reduce(function (flagConfig, flag) {
    flagConfig[flag] = false;
    return flagConfig;
  }, {});
}
Responsibility answered 17/10, 2017 at 1:48 Comment(1)
I just tried this using npm instead of yarn and it works just fine for me. i also added --no-eslintrc because it was trying to reference the local .eslintrc at the location of the fileDenesedengue
B
0

This issue is caused by the changes to the way ESLint loads packages between versions 5 and 6. See here for details.

Plugins and shareable configs are no longer affected by ESLint’s location

Previously, ESLint loaded plugins relative to the location of the ESLint package itself. As a result, we suggested that users with global ESLint installations should also install plugins globally, and users with local ESLint installations should install plugins locally. However, due to a design bug, this strategy caused ESLint to randomly fail to load plugins and shareable configs under certain circumstances, particularly when using package management tools like lerna and Yarn Plug n’ Play.

As a rule of thumb: With ESLint v6, plugins should always be installed locally, even if ESLint was installed globally. More precisely, ESLint v6 resolves plugins relative to the end user’s project by default, and always resolves shareable configs and parsers relative to the location of the config file that imports them.

To address: If you use a global installation of ESLint (e.g. installed with npm install eslint --global) along with plugins, you should install those plugins locally in the projects where you run ESLint. If your config file extends shareable configs and/or parsers, you should ensure that those packages are installed as dependencies of the project containing the config file.

If you use a config file located outside of a local project (with the --config flag), consider installing the plugins as dependencies of that config file, and setting the --resolve-plugins-relative-to flag to the location of the config file.

There's a fair bit of discussion around this, but the current state of affairs (late 2019) seems to be that there are no good solutions at this point other that rolling back to [email protected] :( Watch this issue for more details.

Bakki answered 12/11, 2019 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.