Shareable ESLint config, based on airbnb/javascript, bundled as a plugin.
We want shareable configs to have as low of an overhead as possible. Users shouldn't have to know exactly what plugins are required by the config, install them and manage their versions manually. This plugin contains a shareable config, with plugin dependencies automatically installed.
See eslint/eslint#3458 for further discussion on this topic.
Install ESLint and the config:
npm install --save-dev eslint @thibaudcolas/eslint-plugin-cookbook
Then configure ESLint to use this config. As a .eslintrc.js
in the root of your project:
module.exports = {
// https://github.com/thibaudcolas/eslint-plugin-cookbook
extends: "plugin:@thibaudcolas/cookbook/recommended",
};
This recommended config is Prettier-compatible. First, install Prettier:
npm install --save-dev prettier
Then, to configure Prettier itself, create a prettier.config.js
file in the root of your project. You can use the following to get started:
// https://github.com/thibaudcolas/eslint-plugin-cookbook
module.exports = require("@thibaudcolas/eslint-plugin-cookbook/prettier.config");
Read on: Upgrading to a stricter ESLint config.
Should further customisation be required, rules coming from external plugins require the @thibaudcolas/cookbook
prefix:
module.exports = {
// https://github.com/thibaudcolas/eslint-plugin-cookbook
extends: "plugin:@thibaudcolas/cookbook/recommended",
rules: {
- "react/react-in-jsx-scope": ["warn"],
+ "@thibaudcolas/cookbook/react/react-in-jsx-scope": ["warn"],
- "import/prefer-default-export": ["warn"],
+ "@thibaudcolas/cookbook/import/prefer-default-export": ["warn"],
},
};
- Use ESLint’s
--report-unused-disable-directives
flag to ensure you do not use moreeslint-disable
comments than needed.
To get the most out of this config, it is assumed that projects have the following tools set up:
- Prettier for automated formatting of stylesheets.
- Browserslist for the definition of target browsers (along with autoprefixer and @babel/preset-env).
- no-warning-comments:
1, terms: todo, fixme, xxx, location: start
- import/no-extraneous-dependencies:
2, devDependencies: test/**, tests/**, spec/**, **/__tests__…
- react/jsx-filename-extension:
2, extensions: .js
- no-param-reassign:
2, props: false
- react/forbid-prop-types:
2, forbid: any
Rules of airbnb
- jsx-a11y/anchor-has-content:
error, components:
- jsx-a11y/aria-role:
error, ignoreNonDom: false, ignoreNonDOM: false
- jsx-a11y/aria-props
- jsx-a11y/aria-proptypes
- jsx-a11y/aria-unsupported-elements
- jsx-a11y/alt-text:
error, elements: img, object, area, inputtype=\image\, img: …
- jsx-a11y/img-redundant-alt
- jsx-a11y/label-has-associated-control:
error, labelComponents: , labelAttributes: , controlComponen…
- jsx-a11y/control-has-associated-label:
error, labelAttributes: label, controlComponents: , ignoreEl…
- jsx-a11y/mouse-events-have-key-events
- jsx-a11y/no-access-key
- jsx-a11y/interactive-supports-focus
- jsx-a11y/role-has-required-aria-props
- jsx-a11y/role-supports-aria-props
- jsx-a11y/tabindex-no-positive
- jsx-a11y/heading-has-content:
error, components:
- jsx-a11y/html-has-lang
- jsx-a11y/lang
- jsx-a11y/no-distracting-elements:
error, elements: marquee, blink
- jsx-a11y/scope
- jsx-a11y/click-events-have-key-events
- jsx-a11y/no-static-element-interactions:
error, handlers: onClick, onMouseDown, onMouseUp, onKeyPress…
- jsx-a11y/no-noninteractive-element-interactions:
error, handlers: onClick, onMouseDown, onMouseUp, onKeyPress…
- jsx-a11y/accessible-emoji
- jsx-a11y/aria-activedescendant-has-tabindex
- jsx-a11y/iframe-has-title
- jsx-a11y/no-autofocus:
error, ignoreNonDOM: true
- jsx-a11y/no-redundant-roles
- jsx-a11y/media-has-caption:
error, audio: , video: , track:
- jsx-a11y/no-interactive-element-to-noninteractive-role:
error, tr: none, presentation
- jsx-a11y/no-noninteractive-element-to-interactive-role:
error, ul: listbox, menu, menubar, radiogroup, tablist, tree…
- jsx-a11y/no-noninteractive-tabindex:
error, tags: , roles: tabpanel
- jsx-a11y/anchor-is-valid:
error, components: Link, specialLink: to, aspects: noHref, i…
- no-underscore-dangle:
error, allow: __REDUX_DEVTOOLS_EXTENSION_COMPOSE__, allowAft…
- class-methods-use-this:
error, exceptMethods: render, getInitialState, getDefaultPro…
- react/jsx-boolean-value:
error, never, always:
- react/jsx-no-duplicate-props:
error, ignoreCase: true
- react/jsx-no-undef
- react/jsx-pascal-case:
error, allowAllCaps: true, ignore:
- react/jsx-uses-react
- react/jsx-uses-vars
- react/no-danger:
warn
- react/no-deprecated
- react/no-did-update-set-state
- react/no-will-update-set-state
- react/no-is-mounted
- react/no-string-refs
- react/no-unknown-property
- react/prefer-es6-class:
error, always
- react/prefer-stateless-function:
error, ignorePureComponents: true
- react/prop-types:
error, ignore: , customValidators: , skipUndeclared: false
- react/react-in-jsx-scope
- react/require-render-return
- react/self-closing-comp
- react/sort-comp:
error, order: static-variables, static-methods, instance-var…
- react/jsx-no-target-blank:
error, enforceDynamicLinks: always
- react/jsx-no-comment-textnodes
- react/no-render-return-value
- react/no-find-dom-node
- react/no-danger-with-children
- react/no-unused-prop-types:
error, customValidators: , skipShapeProps: true
- react/style-prop-object
- react/no-unescaped-entities
- react/no-children-prop
- react/no-array-index-key
- react/require-default-props:
error, forbidDefaultForRequired: true
- react/forbid-foreign-prop-types:
warn, allowInPropTypes: true
- react/void-dom-elements-no-children
- react/default-props-match-prop-types:
error, allowRequiredDefaults: false
- react/no-redundant-should-component-update
- react/no-unused-state
- react/no-typos
- react/jsx-curly-brace-presence:
error, props: never, children: never
- react/destructuring-assignment:
error, always
- react/no-access-state-in-setstate
- react/button-has-type:
error, button: true, submit: true, reset: false
- react/no-this-in-sfc
- react/jsx-fragments:
error, syntax
- react/state-in-constructor:
error, always
- react/static-property-placement:
error, property assignment
- react/jsx-props-no-spreading:
error, html: enforce, custom: enforce, exceptions:
- strict:
error, never
- import/no-unresolved:
error, commonjs: true, caseSensitive: true
- import/named
- import/export
- import/no-named-as-default
- import/no-named-as-default-member
- import/no-mutable-exports
- import/no-amd
- import/first
- import/no-duplicates
- import/extensions:
error, ignorePackages, js: never, mjs: never, jsx: never
- import/order:
error, groups: builtin, external, internal
- import/newline-after-import
- import/prefer-default-export
- import/no-absolute-path
- import/no-dynamic-require
- import/no-webpack-loader-syntax
- import/no-named-default
- import/no-self-import
- import/no-cycle
- import/no-useless-path-segments:
error, commonjs: true
- constructor-super
- no-class-assign
- no-const-assign
- no-dupe-class-members
- no-new-symbol
- no-this-before-super
- no-useless-computed-key
- no-useless-constructor
- no-useless-rename:
error, ignoreDestructuring: false, ignoreImport: false, igno…
- no-var
- object-shorthand:
error, always, ignoreConstructors: false, avoidQuotes: true
- prefer-const:
error, destructuring: any, ignoreReadBeforeAssign: true
- prefer-destructuring:
error, VariableDeclarator: array: false, object: true, Assig…
- prefer-numeric-literals
- prefer-rest-params
- prefer-spread
- prefer-template
- require-yield
- symbol-description
- no-delete-var
- no-label-var
- no-restricted-globals:
error, isFinite, isNaN, addEventListener, blur, close, close…
- no-shadow
- no-shadow-restricted-names
- no-undef
- no-undef-init
- no-unused-vars:
error, vars: all, args: after-used, ignoreRestSiblings: true
- no-use-before-define:
error, functions: true, classes: true, variables: true
- camelcase:
error, properties: never, ignoreDestructuring: false, ignore…
- func-names:
warn
- lines-between-class-members:
error, always, exceptAfterSingleLine: false
- lines-around-directive:
error, before: always, after: always
- new-cap:
error, newIsCap: true, newIsCapExceptions: , capIsNew: false…
- no-array-constructor
- no-bitwise
- no-continue
- no-lonely-if
- no-multi-assign
- no-nested-ternary
- no-new-object
- no-plusplus
- no-restricted-syntax:
error, selector: ForInStatement, message: for..in loops iter…
- no-unneeded-ternary:
error, defaultAssignment: false
- one-var:
error, never
- operator-assignment:
error, always
- prefer-object-spread
- spaced-comment:
error, always, line: exceptions: -, +, markers: =, !, block:…
- global-require
- no-buffer-constructor
- no-new-require
- no-path-concat
- for-direction
- getter-return:
error, allowImplicit: true
- no-async-promise-executor
- no-await-in-loop
- no-compare-neg-zero
- no-cond-assign:
error, always
- no-console:
warn
- no-constant-condition:
warn
- no-control-regex
- no-debugger
- no-dupe-args
- no-dupe-keys
- no-duplicate-case
- no-empty
- no-empty-character-class
- no-ex-assign
- no-extra-boolean-cast
- no-func-assign
- no-inner-declarations
- no-invalid-regexp
- no-irregular-whitespace
- no-misleading-character-class
- no-obj-calls
- no-prototype-builtins
- no-regex-spaces
- no-sparse-arrays
- no-template-curly-in-string
- no-unreachable
- no-unsafe-finally
- no-unsafe-negation
- use-isnan
- valid-typeof:
error, requireStringLiterals: true
- array-callback-return:
error, allowImplicit: true, checkForEach: false
- block-scoped-var
- consistent-return
- default-case:
error, commentPattern: ^no default$
- dot-notation:
error, allowKeywords: true, allowPattern:
- eqeqeq:
error, always, null: ignore
- guard-for-in
- max-classes-per-file:
error, 1
- no-alert:
warn
- no-caller
- no-case-declarations
- no-else-return:
error, allowElseIf: false
- no-empty-function:
error, allow: arrowFunctions, functions, methods
- no-empty-pattern
- no-eval
- no-extend-native
- no-extra-bind
- no-extra-label
- no-fallthrough
- no-global-assign:
error, exceptions:
- no-implied-eval
- no-iterator
- no-labels:
error, allowLoop: false, allowSwitch: false
- no-lone-blocks
- no-loop-func
- no-multi-str
- no-new
- no-new-func
- no-new-wrappers
- no-octal
- no-octal-escape
- no-proto
- no-redeclare
- no-restricted-properties:
error, object: arguments, property: callee, message: argumen…
- no-return-assign:
error, always
- no-return-await
- no-script-url
- no-self-assign:
error, props: true
- no-self-compare
- no-sequences
- no-throw-literal
- no-unused-expressions:
error, allowShortCircuit: false, allowTernary: false, allowT…
- no-unused-labels
- no-useless-catch
- no-useless-concat
- no-useless-escape
- no-useless-return
- no-void
- no-with
- prefer-promise-reject-errors:
error, allowEmptyReject: true
- radix
- vars-on-top
- yoda
- react/jsx-no-bind
- react/jsx-child-element-spacing
- react/jsx-closing-bracket-location
- react/jsx-closing-tag-location
- react/jsx-curly-newline
- react/jsx-curly-spacing
- react/jsx-equals-spacing
- react/jsx-first-prop-new-line
- react/jsx-indent
- react/jsx-indent-props
- react/jsx-max-props-per-line
- react/jsx-one-expression-per-line
- react/jsx-props-no-multi-spaces
- react/jsx-tag-spacing
- react/jsx-wrap-multilines
- react/jsx-space-before-closing
- flowtype/boolean-style
- flowtype/delimiter-dangle
- flowtype/generic-spacing
- flowtype/object-type-delimiter
- flowtype/semi
- flowtype/space-after-type-colon
- flowtype/space-before-generic-bracket
- flowtype/space-before-type-colon
- flowtype/union-intersection-spacing
- arrow-body-style
- curly
- lines-around-comment
- max-len
- no-confusing-arrow
- no-mixed-operators
- no-tabs
- no-unexpected-multiline
- prefer-arrow-callback
- quotes
- array-bracket-newline
- array-bracket-spacing
- array-element-newline
- arrow-parens
- arrow-spacing
- block-spacing
- brace-style
- comma-dangle
- comma-spacing
- comma-style
- computed-property-spacing
- dot-location
- eol-last
- func-call-spacing
- function-call-argument-newline
- function-paren-newline
- generator-star
- generator-star-spacing
- implicit-arrow-linebreak
- indent
- jsx-quotes
- key-spacing
- keyword-spacing
- linebreak-style
- multiline-ternary
- newline-per-chained-call
- new-parens
- no-arrow-condition
- no-comma-dangle
- no-extra-parens
- no-extra-semi
- no-floating-decimal
- no-mixed-spaces-and-tabs
- no-multi-spaces
- no-multiple-empty-lines
- no-reserved-keys
- no-space-before-semi
- no-trailing-spaces
- no-whitespace-before-property
- no-wrap-func
- nonblock-statement-body-position
- object-curly-newline
- object-curly-spacing
- object-property-newline
- one-var-declaration-per-line
- operator-linebreak
- padded-blocks
- quote-props
- rest-spread-spacing
- semi
- semi-spacing
- semi-style
- space-after-function-name
- space-after-keywords
- space-before-blocks
- space-before-function-paren
- space-before-function-parentheses
- space-before-keywords
- space-in-brackets
- space-in-parens
- space-infix-ops
- space-return-throw-case
- space-unary-ops
- space-unary-word-ops
- switch-colon-spacing
- template-curly-spacing
- template-tag-spacing
- unicode-bom
- wrap-iife
- wrap-regex
- yield-star-spacing
- indent-legacy
- no-spaced-func
- jsx-a11y/label-has-for
- jsx-a11y/no-onchange
- react/display-name
- react/forbid-dom-props
- react/jsx-handler-names
- react/jsx-key
- react/jsx-no-literals
- react/sort-prop-types
- react/jsx-sort-prop-types
- react/jsx-sort-props
- react/jsx-sort-default-props
- react/no-did-mount-set-state
- react/no-direct-mutation-state
- react/no-multi-comp
- react/no-set-state
- react/require-optimization
- react/forbid-component-props
- react/forbid-elements
- react/boolean-prop-naming
- react/jsx-max-depth
- react/no-unsafe
- react/prefer-read-only-props
- react/jsx-no-script-url
- react/jsx-no-useless-fragment
- react/no-adjacent-inline-elements
- react/function-component-definition
- import/default
- import/namespace
- import/no-deprecated
- import/no-commonjs
- import/no-nodejs-modules
- import/imports-first
- import/no-namespace
- import/no-restricted-paths
- import/max-dependencies
- import/no-internal-modules
- import/unambiguous
- import/no-unassigned-import
- import/no-anonymous-default-export
- import/exports-last
- import/group-exports
- import/no-default-export
- import/no-named-export
- import/dynamic-import-chunkname
- import/no-relative-parent-imports
- import/no-unused-modules
- no-duplicate-imports
- no-restricted-imports
- prefer-reflect
- sort-imports
- init-declarations
- no-catch-shadow
- no-undefined
- capitalized-comments
- consistent-this
- func-name-matching
- func-style
- id-blacklist
- id-length
- id-match
- line-comment-position
- max-depth
- max-lines
- max-lines-per-function
- max-nested-callbacks
- max-params
- max-statements
- max-statements-per-line
- multiline-comment-style
- newline-after-var
- newline-before-return
- no-inline-comments
- no-negated-condition
- no-ternary
- padding-line-between-statements
- prefer-exponentiation-operator
- require-jsdoc
- sort-keys
- sort-vars
- callback-return
- handle-callback-err
- no-mixed-requires
- no-process-env
- no-process-exit
- no-restricted-modules
- no-sync
- no-dupe-else-if
- no-import-assign
- no-setter-return
- no-negated-in-lhs
- require-atomic-updates
- valid-jsdoc
- accessor-pairs
- complexity
- default-param-last
- grouped-accessor-pairs
- no-constructor-return
- no-div-regex
- no-eq-null
- no-native-reassign
- no-implicit-coercion
- no-implicit-globals
- no-invalid-this
- no-magic-numbers
- no-unmodified-loop-condition
- no-useless-call
- prefer-named-capture-group
- prefer-regex-literals
- require-await
- require-unicode-regexp