diff --git a/.editorconfig b/.editorconfig
index 49c154da45..db6f34c77c 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,4 +8,7 @@ trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
# editorconfig-tools is unable to ignore longs strings or urls
-max_line_length = null
+max_line_length = off
+
+[CHANGELOG.md]
+indent_size = false
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
new file mode 100644
index 0000000000..48c68f5955
--- /dev/null
+++ b/.github/workflows/node-pretest.yml
@@ -0,0 +1,26 @@
+name: 'Tests: pretest/posttest'
+
+on: [pull_request, push]
+
+jobs:
+ pretest:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ package:
+ - '..'
+ - eslint-config-airbnb
+ - eslint-config-airbnb-base
+
+ defaults:
+ run:
+ working-directory: "packages/${{ matrix.package }}"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/actions/node/install@main
+ name: 'nvm install lts/* && npm install'
+ with:
+ node-version: 'lts/*'
+ - run: npm run pretest
diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml
new file mode 100644
index 0000000000..6fc77ea08d
--- /dev/null
+++ b/.github/workflows/node.yml
@@ -0,0 +1,163 @@
+name: 'Tests: node.js'
+
+on: [pull_request, push]
+
+jobs:
+ matrix:
+ runs-on: ubuntu-latest
+ outputs:
+ latest: ${{ steps.set-matrix.outputs.requireds }}
+ steps:
+ - uses: ljharb/actions/node/matrix@main
+ id: set-matrix
+ with:
+ versionsAsRoot: true
+ type: 'majors'
+ preset: '^12 || ^14 || ^16 || >= 17'
+
+ base:
+ needs: [matrix]
+ name: 'base config'
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
+ eslint:
+ - 8
+ - 7
+ package:
+ - eslint-config-airbnb-base
+ exclude:
+ - node-version: 10
+ eslint: 8
+ package: eslint-config-airbnb-base
+
+ defaults:
+ run:
+ working-directory: "packages/${{ matrix.package }}"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/actions/node/install@main
+ name: 'nvm install ${{ matrix.node-version }} && npm install'
+ with:
+ before_install: cd "packages/${{ matrix.package }}"
+ node-version: ${{ matrix.node-version }}
+ after_install: |
+ npm install --no-save "eslint@${{ matrix.eslint }}"
+ - run: node -pe "require('eslint/package.json').version"
+ name: 'eslint version'
+ - run: npm run travis
+ - uses: codecov/codecov-action@v2
+
+ react:
+ needs: [matrix]
+ name: 'react config'
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
+ eslint:
+ - 8
+ - 7
+ package:
+ - eslint-config-airbnb
+ react-hooks:
+ - 4
+
+ defaults:
+ run:
+ working-directory: "packages/${{ matrix.package }}"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/actions/node/install@main
+ name: 'nvm install ${{ matrix.node-version }} && npm install'
+ with:
+ before_install: cd "packages/${{ matrix.package }}"
+ node-version: ${{ matrix.node-version }}
+ after_install: |
+ npm install --no-save "eslint@${{ matrix.eslint }}"
+ - run: node -pe "require('eslint/package.json').version"
+ name: 'eslint version'
+ - run: npm install --no-save "eslint-plugin-react-hooks@${{ matrix.react-hooks }}"
+ if: ${{ matrix.react-hooks > 0}}
+ - run: npm run travis
+ - uses: codecov/codecov-action@v2
+
+ prepublish-base:
+ name: 'prepublish tests (base config)'
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ eslint:
+ - 8
+ - 7
+ package:
+ - eslint-config-airbnb-base
+
+ defaults:
+ run:
+ working-directory: "packages/${{ matrix.package }}"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/actions/node/install@main
+ name: 'nvm install lts/* && npm install'
+ with:
+ before_install: cd "packages/${{ matrix.package }}"
+ node-version: lts/*
+ after_install: |
+ npm install --no-save "eslint@${{ matrix.eslint }}"
+ - run: node -pe "require('eslint/package.json').version"
+ name: 'eslint version'
+ - run: npm run pretravis
+ - run: npm run prepublishOnly
+ - run: npm run posttravis
+
+ prepublish-react:
+ name: 'prepublish tests (react config)'
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ eslint:
+ - 8
+ - 7
+ package:
+ - eslint-config-airbnb
+ react-hooks:
+ - 4
+
+ defaults:
+ run:
+ working-directory: "packages/${{ matrix.package }}"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/actions/node/install@main
+ name: 'nvm install lts/* && npm install'
+ with:
+ before_install: cd "packages/${{ matrix.package }}"
+ node-version: lts/*
+ after_install: |
+ npm install --no-save "eslint@${{ matrix.eslint }}"
+ - run: npm install --no-save "eslint-plugin-react-hooks@${{ matrix.react-hooks }}"
+ if: ${{ matrix.react-hooks > 0}}
+ - run: node -pe "require('eslint/package.json').version"
+ name: 'eslint version'
+ - run: npm run pretravis
+ - run: npm run prepublishOnly
+ - run: npm run posttravis
+
+ node:
+ name: 'node 10+'
+ needs: [base, prepublish-base, react, prepublish-react]
+ runs-on: ubuntu-latest
+ steps:
+ - run: 'echo tests completed'
diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml
new file mode 100644
index 0000000000..027aed0797
--- /dev/null
+++ b/.github/workflows/rebase.yml
@@ -0,0 +1,15 @@
+name: Automatic Rebase
+
+on: [pull_request_target]
+
+jobs:
+ _:
+ name: "Automatic Rebase"
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ljharb/rebase@master
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml
new file mode 100644
index 0000000000..549d7b4823
--- /dev/null
+++ b/.github/workflows/require-allow-edits.yml
@@ -0,0 +1,12 @@
+name: Require “Allow Edits”
+
+on: [pull_request_target]
+
+jobs:
+ _:
+ name: "Require “Allow Edits”"
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: ljharb/require-allow-edits@main
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2fcc94de67..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-language: node_js
-node_js:
- - "10"
- - "9"
- - "8"
- - "7"
- - "6"
- - "5"
- - "4"
-before_install:
- - 'nvm install-latest-npm'
-install:
- - 'if [ -n "${PACKAGE-}" ]; then cd "packages/${PACKAGE}"; fi'
- - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
- - 'if [ -n "${ESLINT}" ]; then npm install --no-save "eslint@${ESLINT}"; fi'
-script:
- - 'if [ -n "${PREPUBLISH-}" ]; then npm run pretravis && npm run prepublish && npm run posttravis; elif [ -n "${LINT-}" ]; then npm run lint; else npm run travis; fi'
-sudo: false
-env:
- matrix:
- - 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base'
- - 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb'
- - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb-base'
- - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb'
-matrix:
- fast_finish: true
- include:
- - node_js: "lts/*"
- env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- - node_js: "lts/*"
- env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb
- - node_js: "lts/*"
- env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base
- - node_js: "lts/*"
- env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb
- - node_js: "lts/*"
- env: LINT=true
- exclude:
- - node_js: "5"
- env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- - node_js: "5"
- env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb
- - node_js: "4"
- env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- - node_js: "4"
- env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb
- allow_failures:
- - node_js: "9"
- - node_js: "7"
- - node_js: "5"
- - env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- - env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb
- - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base
- - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb
diff --git a/README.md b/README.md
index fd986b04b5..9a325a355b 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,9 @@ Other Style Guides
- `null`
- `undefined`
- `symbol`
+ - `bigint`
+
+
```javascript
const foo = 1;
@@ -81,7 +84,7 @@ Other Style Guides
console.log(foo, bar); // => 1, 9
```
- - Symbols cannot be faithfully polyfilled, so they should not be used when targeting browsers/environments that don’t support them natively.
+ - Symbols and BigInts cannot be faithfully polyfilled, so they should not be used when targeting browsers/environments that don’t support them natively.
- [1.2](#types--complex) **Complex**: When you access a complex type you work on a reference to its value.
@@ -90,6 +93,8 @@ Other Style Guides
- `array`
- `function`
+
+
```javascript
const foo = [1, 2];
const bar = foo;
@@ -104,7 +109,7 @@ Other Style Guides
## References
- - [2.1](#references--prefer-const) Use `const` for all of your references; avoid using `var`. eslint: [`prefer-const`](https://eslint.org/docs/rules/prefer-const.html), [`no-const-assign`](https://eslint.org/docs/rules/no-const-assign.html)
+ - [2.1](#references--prefer-const) Use `const` for all of your references; avoid using `var`. eslint: [`prefer-const`](https://eslint.org/docs/rules/prefer-const), [`no-const-assign`](https://eslint.org/docs/rules/no-const-assign)
> Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code.
@@ -119,7 +124,7 @@ Other Style Guides
```
- - [2.2](#references--disallow-var) If you must reassign references, use `let` instead of `var`. eslint: [`no-var`](https://eslint.org/docs/rules/no-var.html)
+ - [2.2](#references--disallow-var) If you must reassign references, use `let` instead of `var`. eslint: [`no-var`](https://eslint.org/docs/rules/no-var)
> Why? `let` is block-scoped rather than function-scoped like `var`.
@@ -138,24 +143,28 @@ Other Style Guides
```
- - [2.3](#references--block-scope) Note that both `let` and `const` are block-scoped.
+ - [2.3](#references--block-scope) Note that both `let` and `const` are block-scoped, whereas `var` is function-scoped.
```javascript
// const and let only exist in the blocks they are defined in.
{
let a = 1;
const b = 1;
+ var c = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
+ console.log(c); // Prints 1
```
+ In the above code, you can see that referencing `a` and `b` will produce a ReferenceError, while `c` contains the number. This is because `a` and `b` are block scoped, while `c` is scoped to the containing function.
+
**[⬆ back to top](#table-of-contents)**
## Objects
- - [3.1](#objects--no-new) Use the literal syntax for object creation. eslint: [`no-new-object`](https://eslint.org/docs/rules/no-new-object.html)
+ - [3.1](#objects--no-new) Use the literal syntax for object creation. eslint: [`no-new-object`](https://eslint.org/docs/rules/no-new-object)
```javascript
// bad
@@ -192,7 +201,7 @@ Other Style Guides
```
- - [3.3](#es6-object-shorthand) Use object method shorthand. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand.html)
+ - [3.3](#es6-object-shorthand) Use object method shorthand. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand)
```javascript
// bad
@@ -215,9 +224,9 @@ Other Style Guides
```
- - [3.4](#es6-object-concise) Use property value shorthand. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand.html)
+ - [3.4](#es6-object-concise) Use property value shorthand. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand)
- > Why? It is shorter to write and descriptive.
+ > Why? It is shorter and descriptive.
```javascript
const lukeSkywalker = 'Luke Skywalker';
@@ -264,7 +273,7 @@ Other Style Guides
```
- - [3.6](#objects--quoted-props) Only quote properties that are invalid identifiers. eslint: [`quote-props`](https://eslint.org/docs/rules/quote-props.html)
+ - [3.6](#objects--quoted-props) Only quote properties that are invalid identifiers. eslint: [`quote-props`](https://eslint.org/docs/rules/quote-props)
> Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.
@@ -285,9 +294,9 @@ Other Style Guides
```
- - [3.7](#objects--prototype-builtins) Do not call `Object.prototype` methods directly, such as `hasOwnProperty`, `propertyIsEnumerable`, and `isPrototypeOf`.
+ - [3.7](#objects--prototype-builtins) Do not call `Object.prototype` methods directly, such as `hasOwnProperty`, `propertyIsEnumerable`, and `isPrototypeOf`. eslint: [`no-prototype-builtins`](https://eslint.org/docs/rules/no-prototype-builtins)
- > Why? These methods may be shadowed by properties on the object in question - consider `{ hasOwnProperty: false }` - or, the object may be a null object (`Object.create(null)`).
+ > Why? These methods may be shadowed by properties on the object in question - consider `{ hasOwnProperty: false }` - or, the object may be a null object (`Object.create(null)`). In modern browsers that support ES2022, or with a polyfill such as , `Object.hasOwn` can also be used as an alternative to `Object.prototype.hasOwnProperty.call`.
```javascript
// bad
@@ -296,16 +305,22 @@ Other Style Guides
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
- // best
+ // better
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
+ console.log(has.call(object, key));
+
+ // best
+ console.log(Object.hasOwn(object, key)); // only supported in browsers that support ES2022
+
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
- // ...
- console.log(has.call(object, key));
+ console.log(has(object, key));
+ /* or */
+ console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown
```
- - [3.8](#objects--rest-spread) Prefer the object spread operator over [`Object.assign`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) to shallow-copy objects. Use the object rest operator to get a new object with certain properties omitted.
+ - [3.8](#objects--rest-spread) Prefer the object spread syntax over [`Object.assign`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) to shallow-copy objects. Use the object rest parameter syntax to get a new object with certain properties omitted. eslint: [`prefer-object-spread`](https://eslint.org/docs/rules/prefer-object-spread)
```javascript
// very bad
@@ -329,7 +344,7 @@ Other Style Guides
## Arrays
- - [4.1](#arrays--literals) Use the literal syntax for array creation. eslint: [`no-array-constructor`](https://eslint.org/docs/rules/no-array-constructor.html)
+ - [4.1](#arrays--literals) Use the literal syntax for array creation. eslint: [`no-array-constructor`](https://eslint.org/docs/rules/no-array-constructor)
```javascript
// bad
@@ -371,7 +386,7 @@ Other Style Guides
- - [4.4](#arrays--from-iterable) To convert an iterable object to an array, use spreads `...` instead of [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from).
+ - [4.4](#arrays--from-iterable) To convert an iterable object to an array, use spreads `...` instead of [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
```javascript
const foo = document.querySelectorAll('.foo');
@@ -418,18 +433,16 @@ Other Style Guides
});
// good
- [1, 2, 3].map(x => x + 1);
+ [1, 2, 3].map((x) => x + 1);
// bad - no returned value means `acc` becomes undefined after the first iteration
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
const flatten = acc.concat(item);
- acc[index] = flatten;
});
// good
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
const flatten = acc.concat(item);
- acc[index] = flatten;
return flatten;
});
@@ -455,7 +468,7 @@ Other Style Guides
```
- - [4.8](#arrays--bracket-newline) Use line breaks after open and before close array brackets if an array has multiple lines
+ - [4.8](#arrays--bracket-newline) Use line breaks after opening array brackets and before closing array brackets, if an array has multiple lines
```javascript
// bad
@@ -498,7 +511,7 @@ Other Style Guides
- [5.1](#destructuring--object) Use object destructuring when accessing and using multiple properties of an object. eslint: [`prefer-destructuring`](https://eslint.org/docs/rules/prefer-destructuring)
- > Why? Destructuring saves you from creating temporary references for those properties.
+ > Why? Destructuring saves you from creating temporary references for those properties, and from repetitive access of the object. Repeating object access creates more repetitive code, requires more reading, and creates more opportunities for mistakes. Destructuring objects also provides a single site of definition of the object structure that is used in the block, rather than requiring reading the entire block to determine what is used.
```javascript
// bad
@@ -565,7 +578,7 @@ Other Style Guides
## Strings
- - [6.1](#strings--quotes) Use single quotes `''` for strings. eslint: [`quotes`](https://eslint.org/docs/rules/quotes.html)
+ - [6.1](#strings--quotes) Use single quotes `''` for strings. eslint: [`quotes`](https://eslint.org/docs/rules/quotes)
```javascript
// bad
@@ -600,7 +613,7 @@ Other Style Guides
```
- - [6.3](#es6-template-literals) When programmatically building up strings, use template strings instead of concatenation. eslint: [`prefer-template`](https://eslint.org/docs/rules/prefer-template.html) [`template-curly-spacing`](https://eslint.org/docs/rules/template-curly-spacing)
+ - [6.3](#es6-template-literals) When programmatically building up strings, use template strings instead of concatenation. eslint: [`prefer-template`](https://eslint.org/docs/rules/prefer-template) [`template-curly-spacing`](https://eslint.org/docs/rules/template-curly-spacing)
> Why? Template strings give you a readable, concise syntax with proper newlines and string interpolation features.
@@ -627,7 +640,7 @@ Other Style Guides
```
- - [6.4](#strings--eval) Never use `eval()` on a string, it opens too many vulnerabilities. eslint: [`no-eval`](https://eslint.org/docs/rules/no-eval)
+ - [6.4](#strings--eval) Never use `eval()` on a string; it opens too many vulnerabilities. eslint: [`no-eval`](https://eslint.org/docs/rules/no-eval)
- [6.5](#strings--escaping) Do not unnecessarily escape characters in strings. eslint: [`no-useless-escape`](https://eslint.org/docs/rules/no-useless-escape)
@@ -648,7 +661,7 @@ Other Style Guides
## Functions
- - [7.1](#functions--declarations) Use named function expressions instead of function declarations. eslint: [`func-style`](https://eslint.org/docs/rules/func-style)
+ - [7.1](#functions--declarations) Use named function expressions instead of function declarations. eslint: [`func-style`](https://eslint.org/docs/rules/func-style), [`func-names`](https://eslint.org/docs/latest/rules/func-names)
> Why? Function declarations are hoisted, which means that it’s easy - too easy - to reference the function before it is defined in the file. This harms readability and maintainability. If you find that a function’s definition is large or complex enough that it is interfering with understanding the rest of the file, then perhaps it’s time to extract it to its own module! Don’t forget to explicitly name the expression, regardless of whether or not the name is inferred from the containing variable (which is often the case in modern browsers or when using compilers such as Babel). This eliminates any assumptions made about the Error’s call stack. ([Discussion](https://github.com/airbnb/javascript/issues/794))
@@ -671,7 +684,7 @@ Other Style Guides
```
- - [7.2](#functions--iife) Wrap immediately invoked function expressions in parentheses. eslint: [`wrap-iife`](https://eslint.org/docs/rules/wrap-iife.html)
+ - [7.2](#functions--iife) Wrap immediately invoked function expressions in parentheses. eslint: [`wrap-iife`](https://eslint.org/docs/rules/wrap-iife)
> Why? An immediately invoked function expression is a single unit - wrapping both it, and its invocation parens, in parens, cleanly expresses this. Note that in a world with modules everywhere, you almost never need an IIFE.
@@ -683,7 +696,7 @@ Other Style Guides
```
- - [7.3](#functions--in-blocks) Never declare a function in a non-function block (`if`, `while`, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears. eslint: [`no-loop-func`](https://eslint.org/docs/rules/no-loop-func.html)
+ - [7.3](#functions--in-blocks) Never declare a function in a non-function block (`if`, `while`, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears. eslint: [`no-loop-func`](https://eslint.org/docs/rules/no-loop-func)
- [7.4](#functions--note-on-blocks) **Note:** ECMA-262 defines a `block` as a list of statements. A function declaration is not a statement.
@@ -771,7 +784,7 @@ Other Style Guides
> Why? They are confusing to reason about.
```javascript
- var b = 1;
+ let b = 1;
// bad
function count(a = b++) {
console.log(a);
@@ -783,7 +796,7 @@ Other Style Guides
```
- - [7.9](#functions--defaults-last) Always put default parameters last.
+ - [7.9](#functions--defaults-last) Always put default parameters last. eslint: [`default-param-last`](https://eslint.org/docs/rules/default-param-last)
```javascript
// bad
@@ -804,10 +817,10 @@ Other Style Guides
```javascript
// bad
- var add = new Function('a', 'b', 'return a + b');
+ const add = new Function('a', 'b', 'return a + b');
// still bad
- var subtract = Function('a', 'b', 'return a - b');
+ const subtract = Function('a', 'b', 'return a - b');
```
@@ -827,7 +840,7 @@ Other Style Guides
```
- - [7.12](#functions--mutate-params) Never mutate parameters. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign.html)
+ - [7.12](#functions--mutate-params) Never mutate parameters. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign)
> Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller.
@@ -844,7 +857,7 @@ Other Style Guides
```
- - [7.13](#functions--reassign-params) Never reassign parameters. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign.html)
+ - [7.13](#functions--reassign-params) Never reassign parameters. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign)
> Why? Reassigning parameters can lead to unexpected behavior, especially when accessing the `arguments` object. It can also cause optimization issues, especially in V8.
@@ -872,7 +885,7 @@ Other Style Guides
```
- - [7.14](#functions--spread-vs-apply) Prefer the use of the spread operator `...` to call variadic functions. eslint: [`prefer-spread`](https://eslint.org/docs/rules/prefer-spread)
+ - [7.14](#functions--spread-vs-apply) Prefer the use of the spread syntax `...` to call variadic functions. eslint: [`prefer-spread`](https://eslint.org/docs/rules/prefer-spread)
> Why? It’s cleaner, you don’t need to supply a context, and you can not easily compose `new` with `apply`.
@@ -930,7 +943,7 @@ Other Style Guides
## Arrow Functions
- - [8.1](#arrows--use-them) When you must use an anonymous function (as when passing an inline callback), use arrow function notation. eslint: [`prefer-arrow-callback`](https://eslint.org/docs/rules/prefer-arrow-callback.html), [`arrow-spacing`](https://eslint.org/docs/rules/arrow-spacing.html)
+ - [8.1](#arrows--use-them) When you must use an anonymous function (as when passing an inline callback), use arrow function notation. eslint: [`prefer-arrow-callback`](https://eslint.org/docs/rules/prefer-arrow-callback), [`arrow-spacing`](https://eslint.org/docs/rules/arrow-spacing)
> Why? It creates a version of the function that executes in the context of `this`, which is usually what you want, and is a more concise syntax.
@@ -951,19 +964,19 @@ Other Style Guides
```
- - [8.2](#arrows--implicit-return) If the function body consists of a single statement returning an [expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions) without side effects, omit the braces and use the implicit return. Otherwise, keep the braces and use a `return` statement. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html), [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style.html)
+ - [8.2](#arrows--implicit-return) If the function body consists of a single statement returning an [expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions) without side effects, omit the braces and use the implicit return. Otherwise, keep the braces and use a `return` statement. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens), [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style)
> Why? Syntactic sugar. It reads well when multiple functions are chained together.
```javascript
// bad
- [1, 2, 3].map(number => {
+ [1, 2, 3].map((number) => {
const nextNumber = number + 1;
`A string containing the ${nextNumber}.`;
});
// good
- [1, 2, 3].map(number => `A string containing the ${number}.`);
+ [1, 2, 3].map((number) => `A string containing the ${number + 1}.`);
// good
[1, 2, 3].map((number) => {
@@ -1002,14 +1015,14 @@ Other Style Guides
```javascript
// bad
- ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
+ ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod,
)
);
// good
- ['get', 'post', 'put'].map(httpMethod => (
+ ['get', 'post', 'put'].map((httpMethod) => (
Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod,
@@ -1018,22 +1031,27 @@ Other Style Guides
```
- - [8.4](#arrows--one-arg-parens) If your function takes a single argument and doesn’t use braces, omit the parentheses. Otherwise, always include parentheses around arguments for clarity and consistency. Note: it is also acceptable to always use parentheses, in which case use the [“always” option](https://eslint.org/docs/rules/arrow-parens#always) for eslint. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html)
+ - [8.4](#arrows--one-arg-parens) Always include parentheses around arguments for clarity and consistency. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens)
- > Why? Less visual clutter.
+ > Why? Minimizes diff churn when adding or removing arguments.
```javascript
// bad
- [1, 2, 3].map((x) => x * x);
-
- // good
[1, 2, 3].map(x => x * x);
// good
+ [1, 2, 3].map((x) => x * x);
+
+ // bad
[1, 2, 3].map(number => (
`A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
));
+ // good
+ [1, 2, 3].map((number) => (
+ `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
+ ));
+
// bad
[1, 2, 3].map(x => {
const y = x + 1;
@@ -1052,18 +1070,18 @@ Other Style Guides
```javascript
// bad
- const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
+ const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize;
// bad
- const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
+ const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;
// good
- const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);
+ const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize);
// good
const itemHeight = (item) => {
const { height, largeSize, smallSize } = item;
- return height > 256 ? largeSize : smallSize;
+ return height <= 256 ? largeSize : smallSize;
};
```
@@ -1251,6 +1269,39 @@ Other Style Guides
}
```
+
+ - [9.7](#classes--methods-use-this) Class methods should use `this` or be made into a static method unless an external library or framework requires using specific non-static methods. Being an instance method should indicate that it behaves differently based on properties of the receiver. eslint: [`class-methods-use-this`](https://eslint.org/docs/rules/class-methods-use-this)
+
+ ```javascript
+ // bad
+ class Foo {
+ bar() {
+ console.log('bar');
+ }
+ }
+
+ // good - this is used
+ class Foo {
+ bar() {
+ console.log(this.bar);
+ }
+ }
+
+ // good - constructor is exempt
+ class Foo {
+ constructor() {
+ // ...
+ }
+ }
+
+ // good - static methods aren't expected to use this
+ class Foo {
+ static bar() {
+ console.log('bar');
+ }
+ }
+ ```
+
**[⬆ back to top](#table-of-contents)**
## Modules
@@ -1326,7 +1377,7 @@ Other Style Guides
- [10.5](#modules--no-mutable-exports) Do not export mutable bindings.
- eslint: [`import/no-mutable-exports`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md)
+ eslint: [`import/no-mutable-exports`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md)
> Why? Mutation should be avoided in general, but in particular when exporting mutable bindings. While this technique may be needed for some special cases, in general, only constant references should be exported.
```javascript
@@ -1341,7 +1392,7 @@ Other Style Guides
- [10.6](#modules--prefer-default-export) In modules with a single export, prefer default export over named export.
- eslint: [`import/prefer-default-export`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md)
+ eslint: [`import/prefer-default-export`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md)
> Why? To encourage more files that only ever export one thing, which is better for readability and maintainability.
```javascript
@@ -1354,7 +1405,7 @@ Other Style Guides
- [10.7](#modules--imports-first) Put all `import`s above non-import statements.
- eslint: [`import/first`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md)
+ eslint: [`import/first`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/first.md)
> Why? Since `import`s are hoisted, keeping them all at the top prevents surprising behavior.
```javascript
@@ -1373,6 +1424,7 @@ Other Style Guides
- [10.8](#modules--multiline-imports-over-newlines) Multiline imports should be indented just like multiline array and object literals.
+ eslint: [`object-curly-newline`](https://eslint.org/docs/rules/object-curly-newline)
> Why? The curly braces follow the same indentation rules as every other curly brace block in the style guide, as do the trailing commas.
@@ -1392,7 +1444,7 @@ Other Style Guides
- [10.9](#modules--no-webpack-loader-syntax) Disallow Webpack loader syntax in module import statements.
- eslint: [`import/no-webpack-loader-syntax`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md)
+ eslint: [`import/no-webpack-loader-syntax`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md)
> Why? Since using Webpack syntax in the imports couples the code to a module bundler. Prefer using the loader syntax in `webpack.config.js`.
```javascript
@@ -1405,12 +1457,29 @@ Other Style Guides
import barCss from 'bar.css';
```
+
+ - [10.10](#modules--import-extensions) Do not include JavaScript filename extensions
+ eslint: [`import/extensions`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/extensions.md)
+ > Why? Including extensions inhibits refactoring, and inappropriately hardcodes implementation details of the module you're importing in every consumer.
+
+ ```javascript
+ // bad
+ import foo from './foo.js';
+ import bar from './bar.jsx';
+ import baz from './baz/index.jsx';
+
+ // good
+ import foo from './foo';
+ import bar from './bar';
+ import baz from './baz';
+ ```
+
**[⬆ back to top](#table-of-contents)**
## Iterators and Generators
- - [11.1](#iterators--nope) Don’t use iterators. Prefer JavaScript’s higher-order functions instead of loops like `for-in` or `for-of`. eslint: [`no-iterator`](https://eslint.org/docs/rules/no-iterator.html) [`no-restricted-syntax`](https://eslint.org/docs/rules/no-restricted-syntax)
+ - [11.1](#iterators--nope) Don’t use iterators. Prefer JavaScript’s higher-order functions instead of loops like `for-in` or `for-of`. eslint: [`no-iterator`](https://eslint.org/docs/rules/no-iterator) [`no-restricted-syntax`](https://eslint.org/docs/rules/no-restricted-syntax)
> Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.
@@ -1450,7 +1519,7 @@ Other Style Guides
});
// best (keeping it functional)
- const increasedByOne = numbers.map(num => num + 1);
+ const increasedByOne = numbers.map((num) => num + 1);
```
@@ -1524,7 +1593,7 @@ Other Style Guides
## Properties
- - [12.1](#properties--dot) Use dot notation when accessing properties. eslint: [`dot-notation`](https://eslint.org/docs/rules/dot-notation.html)
+ - [12.1](#properties--dot) Use dot notation when accessing properties. eslint: [`dot-notation`](https://eslint.org/docs/rules/dot-notation)
```javascript
const luke = {
@@ -1554,8 +1623,9 @@ Other Style Guides
const isJedi = getProp('jedi');
```
+
- - [12.3](#es2016-properties--exponentiation-operator) Use exponentiation operator `**` when calculating exponentiations. eslint: [`no-restricted-properties`](https://eslint.org/docs/rules/no-restricted-properties).
+ - [12.3](#es2016-properties--exponentiation-operator) Use exponentiation operator `**` when calculating exponentiations. eslint: [`prefer-exponentiation-operator`](https://eslint.org/docs/rules/prefer-exponentiation-operator).
```javascript
// bad
@@ -1581,7 +1651,7 @@ Other Style Guides
```
- - [13.2](#variables--one-const) Use one `const` or `let` declaration per variable. eslint: [`one-var`](https://eslint.org/docs/rules/one-var.html)
+ - [13.2](#variables--one-const) Use one `const` or `let` declaration per variable or assignment. eslint: [`one-var`](https://eslint.org/docs/rules/one-var)
> Why? It’s easier to add new variable declarations this way, and you never have to worry about swapping out a `;` for a `,` or introducing punctuation-only diffs. You can also step through each declaration with the debugger, instead of jumping through all of them at once.
@@ -1606,7 +1676,7 @@ Other Style Guides
- [13.3](#variables--const-let-group) Group all your `const`s and then group all your `let`s.
- > Why? This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.
+ > Why? This is helpful when later on you might need to assign a variable depending on one of the previously assigned variables.
```javascript
// bad
@@ -1667,6 +1737,7 @@ Other Style Guides
return name;
}
```
+
- [13.5](#variables--no-chain-assignment) Don’t chain variable assignments. eslint: [`no-multi-assign`](https://eslint.org/docs/rules/no-multi-assign)
@@ -1735,7 +1806,7 @@ Other Style Guides
```
- - [13.7](#variables--linebreak) Avoid linebreaks before or after `=` in an assignment. If your assignment violates [`max-len`](https://eslint.org/docs/rules/max-len.html), surround the value in parens. eslint [`operator-linebreak`](https://eslint.org/docs/rules/operator-linebreak.html).
+ - [13.7](#variables--linebreak) Avoid linebreaks before or after `=` in an assignment. If your assignment violates [`max-len`](https://eslint.org/docs/rules/max-len), surround the value in parens. eslint [`operator-linebreak`](https://eslint.org/docs/rules/operator-linebreak).
> Why? Linebreaks surrounding `=` can obfuscate the value of an assignment.
@@ -1765,14 +1836,14 @@ Other Style Guides
```javascript
// bad
- var some_unused_var = 42;
+ const some_unused_var = 42;
// Write-only variables are not considered as used.
- var y = 10;
+ let y = 10;
y = 5;
// A read for a modification of itself is not considered as used.
- var z = 0;
+ let z = 0;
z = z + 1;
// Unused function arguments.
@@ -1786,14 +1857,14 @@ Other Style Guides
return x + y;
}
- var x = 1;
- var y = a + 2;
+ const x = 1;
+ const y = a + 2;
alert(getXPlusY(x, y));
// 'type' is ignored even if unused because it has a rest property sibling.
// This is a form of extracting an object that omits the specified keys.
- var { type, ...coords } = data;
+ const { type, ...coords } = data;
// 'coords' is now the 'data' object without its 'type' property.
```
@@ -1802,7 +1873,7 @@ Other Style Guides
## Hoisting
- - [14.1](#hoisting--about) `var` declarations get hoisted to the top of their closest enclosing function scope, their assignment does not. `const` and `let` declarations are blessed with a new concept called [Temporal Dead Zones (TDZ)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone). It’s important to know why [typeof is no longer safe](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15).
+ - [14.1](#hoisting--about) `var` declarations get hoisted to the top of their closest enclosing function scope, their assignment does not. `const` and `let` declarations are blessed with a new concept called [Temporal Dead Zones (TDZ)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz). It’s important to know why [typeof is no longer safe](https://web.archive.org/web/20200121061528/http://es-discourse.com/t/why-typeof-is-no-longer-safe/15).
```javascript
// we know this wouldn’t work (assuming there
@@ -1894,14 +1965,64 @@ Other Style Guides
}
```
- - For more information refer to [JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/) by [Ben Cherry](http://www.adequatelygood.com/).
+
+ - [14.5](#no-use-before-define) Variables, classes, and functions should be defined before they can be used. eslint: [`no-use-before-define`](https://eslint.org/docs/latest/rules/no-use-before-define)
+
+ > Why? When variables, classes, or functions are declared after being used, it can harm readability since a reader won't know what a thing that's referenced is. It's much clearer for a reader to first encounter the source of a thing (whether imported from another module, or defined in the file) before encountering a use of the thing.
+
+ ```javascript
+ // bad
+
+ // Variable a is being used before it is being defined.
+ console.log(a); // this will be undefined, since while the declaration is hoisted, the initialization is not
+ var a = 10;
+
+ // Function fun is being called before being defined.
+ fun();
+ function fun() {}
+
+ // Class A is being used before being defined.
+ new A(); // ReferenceError: Cannot access 'A' before initialization
+ class A {
+ }
+
+ // `let` and `const` are hoisted, but they don't have a default initialization.
+ // The variables 'a' and 'b' are in a Temporal Dead Zone where JavaScript
+ // knows they exist (declaration is hoisted) but they are not accessible
+ // (as they are not yet initialized).
+
+ console.log(a); // ReferenceError: Cannot access 'a' before initialization
+ console.log(b); // ReferenceError: Cannot access 'b' before initialization
+ let a = 10;
+ const b = 5;
+
+
+ // good
+
+ var a = 10;
+ console.log(a); // 10
+
+ function fun() {}
+ fun();
+
+ class A {
+ }
+ new A();
+
+ let a = 10;
+ const b = 5;
+ console.log(a); // 10
+ console.log(b); // 5
+ ```
+
+ - For more information refer to [JavaScript Scoping & Hoisting](https://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/) by [Ben Cherry](https://www.adequatelygood.com/).
**[⬆ back to top](#table-of-contents)**
## Comparison Operators & Equality
- - [15.1](#comparison--eqeqeq) Use `===` and `!==` over `==` and `!=`. eslint: [`eqeqeq`](https://eslint.org/docs/rules/eqeqeq.html)
+ - [15.1](#comparison--eqeqeq) Use `===` and `!==` over `==` and `!=`. eslint: [`eqeqeq`](https://eslint.org/docs/rules/eqeqeq)
- [15.2](#comparison--if) Conditional statements such as the `if` statement evaluate their expression using coercion with the `ToBoolean` abstract method and always follow these simple rules:
@@ -1956,10 +2077,10 @@ Other Style Guides
```
- - [15.4](#comparison--moreinfo) For more information see [Truth Equality and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll.
+ - [15.4](#comparison--moreinfo) For more information see [Truth, Equality, and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll.
- - [15.5](#comparison--switch-blocks) Use braces to create blocks in `case` and `default` clauses that contain lexical declarations (e.g. `let`, `const`, `function`, and `class`). eslint: [`no-case-declarations`](https://eslint.org/docs/rules/no-case-declarations.html)
+ - [15.5](#comparison--switch-blocks) Use braces to create blocks in `case` and `default` clauses that contain lexical declarations (e.g. `let`, `const`, `function`, and `class`). eslint: [`no-case-declarations`](https://eslint.org/docs/rules/no-case-declarations)
> Why? Lexical declarations are visible in the entire `switch` block but only get initialized when assigned, which only happens when its `case` is reached. This causes problems when multiple `case` clauses attempt to define the same thing.
@@ -2007,7 +2128,7 @@ Other Style Guides
```
- - [15.6](#comparison--nested-ternaries) Ternaries should not be nested and generally be single line expressions. eslint: [`no-nested-ternary`](https://eslint.org/docs/rules/no-nested-ternary.html)
+ - [15.6](#comparison--nested-ternaries) Ternaries should not be nested and generally be single line expressions. eslint: [`no-nested-ternary`](https://eslint.org/docs/rules/no-nested-ternary)
```javascript
// bad
@@ -2028,22 +2149,25 @@ Other Style Guides
```
- - [15.7](#comparison--unneeded-ternary) Avoid unneeded ternary statements. eslint: [`no-unneeded-ternary`](https://eslint.org/docs/rules/no-unneeded-ternary.html)
+ - [15.7](#comparison--unneeded-ternary) Avoid unneeded ternary statements. eslint: [`no-unneeded-ternary`](https://eslint.org/docs/rules/no-unneeded-ternary)
```javascript
// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
+ const quux = a != null ? a : b;
// good
const foo = a || b;
const bar = !!c;
const baz = !c;
+ const quux = a ?? b;
```
- - [15.8](#comparison--no-mixed-operators) When mixing operators, enclose them in parentheses. The only exception is the standard arithmetic operators (`+`, `-`, `*`, & `/`) since their precedence is broadly understood. eslint: [`no-mixed-operators`](https://eslint.org/docs/rules/no-mixed-operators.html)
+ - [15.8](#comparison--no-mixed-operators) When mixing operators, enclose them in parentheses. The only exception is the standard arithmetic operators: `+`, `-`, and `**` since their precedence is broadly understood. We recommend enclosing `/` and `*` in parentheses because their precedence can be ambiguous when they are mixed.
+ eslint: [`no-mixed-operators`](https://eslint.org/docs/rules/no-mixed-operators)
> Why? This improves readability and clarifies the developer’s intention.
@@ -2060,11 +2184,14 @@ Other Style Guides
return d;
}
+ // bad
+ const bar = a + b / c * d;
+
// good
const foo = (a && b < 0) || c > 0 || (d + 1 === 0);
// good
- const bar = (a ** b) - (5 % d);
+ const bar = a ** b - (5 % d);
// good
if (a || (b && c)) {
@@ -2072,7 +2199,34 @@ Other Style Guides
}
// good
- const bar = a + b / c * d;
+ const bar = a + (b / c) * d;
+ ```
+
+
+ - [15.9](#nullish-coalescing-operator) The nullish coalescing operator (`??`) is a logical operator that returns its right-hand side operand when its left-hand side operand is `null` or `undefined`. Otherwise, it returns the left-hand side operand.
+
+ > Why? It provides precision by distinguishing null/undefined from other falsy values, enhancing code clarity and predictability.
+
+ ```javascript
+ // bad
+ const value = 0 ?? 'default';
+ // returns 0, not 'default'
+
+ // bad
+ const value = '' ?? 'default';
+ // returns '', not 'default'
+
+ // good
+ const value = null ?? 'default';
+ // returns 'default'
+
+ // good
+ const user = {
+ name: 'John',
+ age: null
+ };
+ const age = user.age ?? 18;
+ // returns 18
```
**[⬆ back to top](#table-of-contents)**
@@ -2080,7 +2234,7 @@ Other Style Guides
## Blocks
- - [16.1](#blocks--braces) Use braces with all multi-line blocks. eslint: [`nonblock-statement-body-position`](https://eslint.org/docs/rules/nonblock-statement-body-position)
+ - [16.1](#blocks--braces) Use braces with all multiline blocks. eslint: [`nonblock-statement-body-position`](https://eslint.org/docs/rules/nonblock-statement-body-position)
```javascript
// bad
@@ -2105,7 +2259,7 @@ Other Style Guides
```
- - [16.2](#blocks--cuddled-elses) If you’re using multi-line blocks with `if` and `else`, put `else` on the same line as your `if` block’s closing brace. eslint: [`brace-style`](https://eslint.org/docs/rules/brace-style.html)
+ - [16.2](#blocks--cuddled-elses) If you’re using multiline blocks with `if` and `else`, put `else` on the same line as your `if` block’s closing brace. eslint: [`brace-style`](https://eslint.org/docs/rules/brace-style)
```javascript
// bad
@@ -2249,7 +2403,7 @@ Other Style Guides
}
```
-
+
- [17.2](#control-statements--value-selection) Don't use selection operators in place of control statements.
```javascript
@@ -2267,7 +2421,7 @@ Other Style Guides
## Comments
- - [18.1](#comments--multiline) Use `/** ... */` for multi-line comments.
+ - [18.1](#comments--multiline) Use `/** ... */` for multiline comments.
```javascript
// bad
@@ -2408,7 +2562,7 @@ Other Style Guides
## Whitespace
- - [19.1](#whitespace--spaces) Use soft tabs (space character) set to 2 spaces. eslint: [`indent`](https://eslint.org/docs/rules/indent.html)
+ - [19.1](#whitespace--spaces) Use soft tabs (space character) set to 2 spaces. eslint: [`indent`](https://eslint.org/docs/rules/indent)
```javascript
// bad
@@ -2428,7 +2582,7 @@ Other Style Guides
```
- - [19.2](#whitespace--before-blocks) Place 1 space before the leading brace. eslint: [`space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks.html)
+ - [19.2](#whitespace--before-blocks) Place 1 space before the leading brace. eslint: [`space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks)
```javascript
// bad
@@ -2455,7 +2609,7 @@ Other Style Guides
```
- - [19.3](#whitespace--around-keywords) Place 1 space before the opening parenthesis in control statements (`if`, `while` etc.). Place no space between the argument list and the function name in function calls and declarations. eslint: [`keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing.html)
+ - [19.3](#whitespace--around-keywords) Place 1 space before the opening parenthesis in control statements (`if`, `while` etc.). Place no space between the argument list and the function name in function calls and declarations. eslint: [`keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing)
```javascript
// bad
@@ -2480,7 +2634,7 @@ Other Style Guides
```
- - [19.4](#whitespace--infix-ops) Set off operators with spaces. eslint: [`space-infix-ops`](https://eslint.org/docs/rules/space-infix-ops.html)
+ - [19.4](#whitespace--infix-ops) Set off operators with spaces. eslint: [`space-infix-ops`](https://eslint.org/docs/rules/space-infix-ops)
```javascript
// bad
@@ -2491,7 +2645,7 @@ Other Style Guides
```
- - [19.5](#whitespace--newline-at-end) End files with a single newline character. eslint: [`eol-last`](https://github.com/eslint/eslint/blob/master/docs/rules/eol-last.md)
+ - [19.5](#whitespace--newline-at-end) End files with a single newline character. eslint: [`eol-last`](https://eslint.org/docs/rules/eol-last)
```javascript
// bad
@@ -2542,7 +2696,7 @@ Other Style Guides
// bad
const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
- .attr('transform', `translate(${radius + margin},${radius + margin})`)
+ .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
.call(tron.led);
// good
@@ -2552,11 +2706,15 @@ Other Style Guides
.classed('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
- .attr('transform', `translate(${radius + margin},${radius + margin})`)
+ .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
.call(tron.led);
// good
const leds = stage.selectAll('.led').data(data);
+ const svg = leds.enter().append('svg:svg');
+ svg.classed('led', true).attr('width', (radius + margin) * 2);
+ const g = svg.append('svg:g');
+ g.attr('transform', `translate(${radius + margin}, ${radius + margin})`).call(tron.led);
```
@@ -2618,7 +2776,7 @@ Other Style Guides
```
- - [19.8](#whitespace--padded-blocks) Do not pad your blocks with blank lines. eslint: [`padded-blocks`](https://eslint.org/docs/rules/padded-blocks.html)
+ - [19.8](#whitespace--padded-blocks) Do not pad your blocks with blank lines. eslint: [`padded-blocks`](https://eslint.org/docs/rules/padded-blocks)
```javascript
// bad
@@ -2631,7 +2789,7 @@ Other Style Guides
// bad
if (baz) {
- console.log(qux);
+ console.log(quux);
} else {
console.log(foo);
@@ -2652,14 +2810,68 @@ Other Style Guides
// good
if (baz) {
- console.log(qux);
+ console.log(quux);
} else {
console.log(foo);
}
```
+
+ - [19.9](#whitespace--no-multiple-blanks) Do not use multiple blank lines to pad your code. eslint: [`no-multiple-empty-lines`](https://eslint.org/docs/rules/no-multiple-empty-lines)
+
+
+ ```javascript
+ // bad
+ class Person {
+ constructor(fullName, email, birthday) {
+ this.fullName = fullName;
+
+
+ this.email = email;
+
+
+ this.setAge(birthday);
+ }
+
+
+ setAge(birthday) {
+ const today = new Date();
+
+
+ const age = this.getAge(today, birthday);
+
+
+ this.age = age;
+ }
+
+
+ getAge(today, birthday) {
+ // ..
+ }
+ }
+
+ // good
+ class Person {
+ constructor(fullName, email, birthday) {
+ this.fullName = fullName;
+ this.email = email;
+ this.setAge(birthday);
+ }
+
+ setAge(birthday) {
+ const today = new Date();
+ const age = getAge(today, birthday);
+ this.age = age;
+ }
+
+ getAge(today, birthday) {
+ // ..
+ }
+ }
+ ```
+
- - [19.9](#whitespace--in-parens) Do not add spaces inside parentheses. eslint: [`space-in-parens`](https://eslint.org/docs/rules/space-in-parens.html)
+ - [19.10](#whitespace--in-parens) Do not add spaces inside parentheses. eslint: [`space-in-parens`](https://eslint.org/docs/rules/space-in-parens)
```javascript
// bad
@@ -2684,7 +2896,7 @@ Other Style Guides
```
- - [19.10](#whitespace--in-brackets) Do not add spaces inside brackets. eslint: [`array-bracket-spacing`](https://eslint.org/docs/rules/array-bracket-spacing.html)
+ - [19.11](#whitespace--in-brackets) Do not add spaces inside brackets. eslint: [`array-bracket-spacing`](https://eslint.org/docs/rules/array-bracket-spacing)
```javascript
// bad
@@ -2697,7 +2909,7 @@ Other Style Guides
```
- - [19.11](#whitespace--in-braces) Add spaces inside curly braces. eslint: [`object-curly-spacing`](https://eslint.org/docs/rules/object-curly-spacing.html)
+ - [19.12](#whitespace--in-braces) Add spaces inside curly braces. eslint: [`object-curly-spacing`](https://eslint.org/docs/rules/object-curly-spacing)
```javascript
// bad
@@ -2708,7 +2920,7 @@ Other Style Guides
```
- - [19.12](#whitespace--max-len) Avoid having lines of code that are longer than 100 characters (including whitespace). Note: per [above](#strings--line-length), long strings are exempt from this rule, and should not be broken up. eslint: [`max-len`](https://eslint.org/docs/rules/max-len.html)
+ - [19.13](#whitespace--max-len) Avoid having lines of code that are longer than 100 characters (including whitespace). Note: per [above](#strings--line-length), long strings are exempt from this rule, and should not be broken up. eslint: [`max-len`](https://eslint.org/docs/rules/max-len)
> Why? This ensures readability and maintainability.
@@ -2727,6 +2939,14 @@ Other Style Guides
&& jsonData.foo.bar.baz.quux
&& jsonData.foo.bar.baz.quux.xyzzy;
+ // better
+ const foo = jsonData
+ ?.foo
+ ?.bar
+ ?.baz
+ ?.quux
+ ?.xyzzy;
+
// good
$.ajax({
method: 'POST',
@@ -2738,7 +2958,7 @@ Other Style Guides
```
- - [19.13](#whitespace--block-spacing) Require consistent spacing inside an open block token and the next token on the same line. This rule also enforces consistent spacing inside a close block token and previous token on the same line. eslint: [`block-spacing`](https://eslint.org/docs/rules/block-spacing)
+ - [19.14](#whitespace--block-spacing) Require consistent spacing inside an open block token and the next token on the same line. This rule also enforces consistent spacing inside a close block token and previous token on the same line. eslint: [`block-spacing`](https://eslint.org/docs/rules/block-spacing)
```javascript
// bad
@@ -2751,37 +2971,37 @@ Other Style Guides
```
- - [19.14](#whitespace--comma-spacing) Avoid spaces before commas and require a space after commas. eslint: [`comma-spacing`](https://eslint.org/docs/rules/comma-spacing)
+ - [19.15](#whitespace--comma-spacing) Avoid spaces before commas and require a space after commas. eslint: [`comma-spacing`](https://eslint.org/docs/rules/comma-spacing)
```javascript
// bad
- var foo = 1,bar = 2;
- var arr = [1 , 2];
+ const foo = 1,bar = 2;
+ const arr = [1 , 2];
// good
- var foo = 1, bar = 2;
- var arr = [1, 2];
+ const foo = 1, bar = 2;
+ const arr = [1, 2];
```
- - [19.15](#whitespace--computed-property-spacing) Enforce spacing inside of computed properties. eslint: [`computed-property-spacing`](https://eslint.org/docs/rules/computed-property-spacing)
+ - [19.16](#whitespace--computed-property-spacing) Enforce spacing inside of computed property brackets. eslint: [`computed-property-spacing`](https://eslint.org/docs/rules/computed-property-spacing)
```javascript
// bad
obj[foo ]
obj[ 'foo']
- var x = {[ b ]: a}
+ const x = {[ b ]: a}
obj[foo[ bar ]]
// good
obj[foo]
obj['foo']
- var x = { [b]: a }
+ const x = { [b]: a }
obj[foo[bar]]
```
- - [19.16](#whitespace--func-call-spacing) Enforce spacing between functions and their invocations. eslint: [`func-call-spacing`](https://eslint.org/docs/rules/func-call-spacing)
+ - [19.17](#whitespace--func-call-spacing) Avoid spaces between functions and their invocations. eslint: [`func-call-spacing`](https://eslint.org/docs/rules/func-call-spacing)
```javascript
// bad
@@ -2795,36 +3015,45 @@ Other Style Guides
```
- - [19.17](#whitespace--key-spacing) Enforce spacing between keys and values in object literal properties. eslint: [`key-spacing`](https://eslint.org/docs/rules/key-spacing)
+ - [19.18](#whitespace--key-spacing) Enforce spacing between keys and values in object literal properties. eslint: [`key-spacing`](https://eslint.org/docs/rules/key-spacing)
```javascript
// bad
- var obj = { "foo" : 42 };
- var obj2 = { "foo":42 };
+ const obj = { foo : 42 };
+ const obj2 = { foo:42 };
// good
- var obj = { "foo": 42 };
+ const obj = { foo: 42 };
```
- - [19.18](#whitespace--no-trailing-spaces) Avoid trailing spaces at the end of lines. eslint: [`no-trailing-spaces`](https://eslint.org/docs/rules/no-trailing-spaces)
+ - [19.19](#whitespace--no-trailing-spaces) Avoid trailing spaces at the end of lines. eslint: [`no-trailing-spaces`](https://eslint.org/docs/rules/no-trailing-spaces)
- - [19.19](#whitespace--no-multiple-empty-lines) Avoid multiple empty lines and only allow one newline at the end of files. eslint: [`no-multiple-empty-lines`](https://eslint.org/docs/rules/no-multiple-empty-lines)
+ - [19.20](#whitespace--no-multiple-empty-lines) Avoid multiple empty lines, only allow one newline at the end of files, and avoid a newline at the beginning of files. eslint: [`no-multiple-empty-lines`](https://eslint.org/docs/rules/no-multiple-empty-lines)
```javascript
- // bad
- var x = 1;
+ // bad - multiple empty lines
+ const x = 1;
+ const y = 2;
- var y = 2;
+ // bad - 2+ newlines at end of file
+ const x = 1;
+ const y = 2;
+
+
+ // bad - 1+ newline(s) at beginning of file
+
+ const x = 1;
+ const y = 2;
// good
- var x = 1;
+ const x = 1;
+ const y = 2;
- var y = 2;
```
@@ -2833,7 +3062,7 @@ Other Style Guides
## Commas
- - [20.1](#commas--leading-trailing) Leading commas: **Nope.** eslint: [`comma-style`](https://eslint.org/docs/rules/comma-style.html)
+ - [20.1](#commas--leading-trailing) Leading commas: **Nope.** eslint: [`comma-style`](https://eslint.org/docs/rules/comma-style)
```javascript
// bad
@@ -2868,7 +3097,7 @@ Other Style Guides
```
- - [20.2](#commas--dangling) Additional trailing comma: **Yup.** eslint: [`comma-dangle`](https://eslint.org/docs/rules/comma-dangle.html)
+ - [20.2](#commas--dangling) Additional trailing comma: **Yup.** eslint: [`comma-dangle`](https://eslint.org/docs/rules/comma-dangle)
> Why? This leads to cleaner git diffs. Also, transpilers like Babel will remove the additional trailing comma in the transpiled code which means you don’t have to worry about the [trailing comma problem](https://github.com/airbnb/javascript/blob/es5-deprecated/es5/README.md#commas) in legacy browsers.
@@ -2968,15 +3197,15 @@ Other Style Guides
## Semicolons
- - [21.1](#semicolons--required) **Yup.** eslint: [`semi`](https://eslint.org/docs/rules/semi.html)
+ - [21.1](#semicolons--required) **Yup.** eslint: [`semi`](https://eslint.org/docs/rules/semi)
- > Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called [Automatic Semicolon Insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion) to determine whether or not it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.
+ > Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called [Automatic Semicolon Insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion) to determine whether it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.
```javascript
// bad - raises exception
const luke = {}
const leia = {}
- [luke, leia].forEach(jedi => jedi.father = 'vader')
+ [luke, leia].forEach((jedi) => jedi.father = 'vader')
// bad - raises exception
const reaction = "No! That’s impossible!"
@@ -2999,7 +3228,7 @@ Other Style Guides
});
// good
- const reaction = "No! That’s impossible!";
+ const reaction = 'No! That’s impossible!';
(async function meanwhileOnTheFalcon() {
// handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
// ...
@@ -3021,7 +3250,7 @@ Other Style Guides
- [22.1](#coercion--explicit) Perform type coercion at the beginning of the statement.
- - [22.2](#coercion--strings) Strings: eslint: [`no-new-wrappers`](https://eslint.org/docs/rules/no-new-wrappers)
+ - [22.2](#coercion--strings) Strings: eslint: [`no-new-wrappers`](https://eslint.org/docs/rules/no-new-wrappers)
```javascript
// => this.reviewScore = 9;
@@ -3042,6 +3271,8 @@ Other Style Guides
- [22.3](#coercion--numbers) Numbers: Use `Number` for type casting and `parseInt` always with a radix for parsing strings. eslint: [`radix`](https://eslint.org/docs/rules/radix) [`no-new-wrappers`](https://eslint.org/docs/rules/no-new-wrappers)
+ > Why? The `parseInt` function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading whitespace in string is ignored. If radix is `undefined` or `0`, it is assumed to be `10` except when the number begins with the character pairs `0x` or `0X`, in which case a radix of 16 is assumed. This differs from ECMAScript 3, which merely discouraged (but allowed) octal interpretation. Many implementations have not adopted this behavior as of 2013. And, because older browsers must be supported, always specify a radix.
+
```javascript
const inputValue = '4';
@@ -3065,7 +3296,7 @@ Other Style Guides
```
- - [22.4](#coercion--comment-deviations) If for whatever reason you are doing something wild and `parseInt` is your bottleneck and need to use Bitshift for [performance reasons](https://jsperf.com/coercion-vs-casting/3), leave a comment explaining why and what you’re doing.
+ - [22.4](#coercion--comment-deviations) If for whatever reason you are doing something wild and `parseInt` is your bottleneck and need to use Bitshift for [performance reasons](https://web.archive.org/web/20200414205431/https://jsperf.com/coercion-vs-casting/3), leave a comment explaining why and what you’re doing.
```javascript
// good
@@ -3122,7 +3353,7 @@ Other Style Guides
```
- - [23.2](#naming--camelCase) Use camelCase when naming objects, functions, and instances. eslint: [`camelcase`](https://eslint.org/docs/rules/camelcase.html)
+ - [23.2](#naming--camelCase) Use camelCase when naming objects, functions, and instances. eslint: [`camelcase`](https://eslint.org/docs/rules/camelcase)
```javascript
// bad
@@ -3136,7 +3367,7 @@ Other Style Guides
```
- - [23.3](#naming--PascalCase) Use PascalCase only when naming constructors or classes. eslint: [`new-cap`](https://eslint.org/docs/rules/new-cap.html)
+ - [23.3](#naming--PascalCase) Use PascalCase only when naming constructors or classes. eslint: [`new-cap`](https://eslint.org/docs/rules/new-cap)
```javascript
// bad
@@ -3161,7 +3392,7 @@ Other Style Guides
```
- - [23.4](#naming--leading-underscore) Do not use trailing or leading underscores. eslint: [`no-underscore-dangle`](https://eslint.org/docs/rules/no-underscore-dangle.html)
+ - [23.4](#naming--leading-underscore) Do not use trailing or leading underscores. eslint: [`no-underscore-dangle`](https://eslint.org/docs/rules/no-underscore-dangle)
> Why? JavaScript does not have the concept of privacy in terms of properties or methods. Although a leading underscore is a common convention to mean “private”, in fact, these properties are fully public, and as such, are part of your public API contract. This convention might lead developers to wrongly think that a change won’t count as breaking, or that tests aren’t needed. tl;dr: if you want something to be “private”, it must not be observably present.
@@ -3175,7 +3406,7 @@ Other Style Guides
this.firstName = 'Panda';
// good, in environments where WeakMaps are available
- // see https://kangax.github.io/compat-table/es6/#test-WeakMap
+ // see https://compat-table.github.io/compat-table/es6/#test-WeakMap
const firstNames = new WeakMap();
firstNames.set(this, 'Panda');
```
@@ -3268,7 +3499,7 @@ Other Style Guides
```
- - [23.9](#naming--Acronyms-and-Initialisms) Acronyms and initialisms should always be all capitalized, or all lowercased.
+ - [23.9](#naming--Acronyms-and-Initialisms) Acronyms and initialisms should always be all uppercased, or all lowercased.
> Why? Names are for readability, not to appease a computer algorithm.
@@ -3308,7 +3539,7 @@ Other Style Guides
> Why? This is an additional tool to assist in situations where the programmer would be unsure if a variable might ever change. UPPERCASE_VARIABLES are letting the programmer know that they can trust the variable (and its properties) not to change.
- What about all `const` variables? - This is unnecessary, so uppercasing should not be used for constants within a file. It should be used for exported constants however.
- - What about exported objects? - Uppercase at the top level of export (e.g. `EXPORTED_OBJECT.key`) and maintain that all nested properties do not change.
+ - What about exported objects? - Uppercase at the top level of export (e.g. `EXPORTED_OBJECT.key`) and maintain that all nested properties do not change.
```javascript
// bad
@@ -3337,7 +3568,7 @@ Other Style Guides
// good
export const MAPPING = {
- key: 'value'
+ key: 'value',
};
```
@@ -3415,7 +3646,7 @@ Other Style Guides
## Events
- - [25.1](#events--hash) When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass an object literal (also known as a "hash") instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:
+ - [25.1](#events--hash) When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass an object literal (also known as a "hash") instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:
```javascript
// bad
@@ -3488,7 +3719,7 @@ Other Style Guides
```
- - [26.3](#jquery--queries) For DOM queries use Cascading `$('.sidebar ul')` or parent > child `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
+ - [26.3](#jquery--queries) For DOM queries use Cascading `$('.sidebar ul')` or parent > child `$('.sidebar > ul')`. [jsPerf](https://web.archive.org/web/20200414183810/https://jsperf.com/jquery-find-vs-context-sel/16)
- [26.4](#jquery--find) Use `find` with scoped jQuery object queries.
@@ -3515,7 +3746,7 @@ Other Style Guides
## ECMAScript 5 Compatibility
- - [27.1](#es5-compat--kangax) Refer to [Kangax](https://twitter.com/kangax/)’s ES5 [compatibility table](https://kangax.github.io/es5-compat-table/).
+ - [27.1](#es5-compat--kangax) Refer to [Kangax](https://twitter.com/kangax/)’s ES5 [compatibility table](https://compat-table.github.io/compat-table/es5/).
**[⬆ back to top](#table-of-contents)**
@@ -3605,20 +3836,20 @@ Other Style Guides
- Be cautious about stubs and mocks - they can make your tests more brittle.
- We primarily use [`mocha`](https://www.npmjs.com/package/mocha) and [`jest`](https://www.npmjs.com/package/jest) at Airbnb. [`tape`](https://www.npmjs.com/package/tape) is also used occasionally for small, separate modules.
- 100% test coverage is a good goal to strive for, even if it’s not always practical to reach it.
- - Whenever you fix a bug, _write a regression test_. A bug fixed without a regression test is almost certainly going to break again in the future.
+ - Whenever you fix a bug, *write a regression test*. A bug fixed without a regression test is almost certainly going to break again in the future.
**[⬆ back to top](#table-of-contents)**
## Performance
- [On Layout & Web Performance](https://www.kellegous.com/j/2013/01/26/layout-performance/)
- - [String vs Array Concat](https://jsperf.com/string-vs-array-concat/2)
- - [Try/Catch Cost In a Loop](https://jsperf.com/try-catch-in-loop-cost)
- - [Bang Function](https://jsperf.com/bang-function)
- - [jQuery Find vs Context, Selector](https://jsperf.com/jquery-find-vs-context-sel/13)
- - [innerHTML vs textContent for script text](https://jsperf.com/innerhtml-vs-textcontent-for-script-text)
- - [Long String Concatenation](https://jsperf.com/ya-string-concat)
- - [Are Javascript functions like `map()`, `reduce()`, and `filter()` optimized for traversing arrays?](https://www.quora.com/JavaScript-programming-language-Are-Javascript-functions-like-map-reduce-and-filter-already-optimized-for-traversing-array/answer/Quildreen-Motta)
+ - [String vs Array Concat](https://web.archive.org/web/20200414200857/https://jsperf.com/string-vs-array-concat/2)
+ - [Try/Catch Cost In a Loop](https://web.archive.org/web/20200414190827/https://jsperf.com/try-catch-in-loop-cost/12)
+ - [Bang Function](https://web.archive.org/web/20200414205426/https://jsperf.com/bang-function)
+ - [jQuery Find vs Context, Selector](https://web.archive.org/web/20200414200850/https://jsperf.com/jquery-find-vs-context-sel/164)
+ - [innerHTML vs textContent for script text](https://web.archive.org/web/20200414205428/https://jsperf.com/innerhtml-vs-textcontent-for-script-text)
+ - [Long String Concatenation](https://web.archive.org/web/20200414203914/https://jsperf.com/ya-string-concat/38)
+ - [Are JavaScript functions like `map()`, `reduce()`, and `filter()` optimized for traversing arrays?](https://www.quora.com/JavaScript-programming-language-Are-Javascript-functions-like-map-reduce-and-filter-already-optimized-for-traversing-array/answer/Quildreen-Motta)
- Loading...
**[⬆ back to top](#table-of-contents)**
@@ -3628,24 +3859,26 @@ Other Style Guides
**Learning ES6+**
- [Latest ECMA spec](https://tc39.github.io/ecma262/)
- - [ExploringJS](http://exploringjs.com/)
- - [ES6 Compatibility Table](https://kangax.github.io/compat-table/es6/)
- - [Comprehensive Overview of ES6 Features](http://es6-features.org/)
+ - [ExploringJS](https://exploringjs.com/)
+ - [ES6 Compatibility Table](https://compat-table.github.io/compat-table/es6/)
+ - [Comprehensive Overview of ES6 Features](https://web.archive.org/web/20240404212626/http://es6-features.org/)
+ - [JavaScript Roadmap](https://roadmap.sh/javascript)
**Read This**
- - [Standard ECMA-262](http://www.ecma-international.org/ecma-262/6.0/index.html)
+ - [Standard ECMA-262](https://www.ecma-international.org/ecma-262/6.0/index.html)
**Tools**
- Code Style Linters
- [ESlint](https://eslint.org/) - [Airbnb Style .eslintrc](https://github.com/airbnb/javascript/blob/master/linters/.eslintrc)
- - [JSHint](http://jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/.jshintrc)
+ - [JSHint](https://jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/.jshintrc)
- Neutrino Preset - [@neutrinojs/airbnb](https://neutrinojs.org/packages/airbnb/)
**Other Style Guides**
- - [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml)
+ - [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)
+ - [Google JavaScript Style Guide (Old)](https://google.github.io/styleguide/javascriptguide.xml)
- [jQuery Core Style Guidelines](https://contribute.jquery.org/style-guide/js/)
- [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwaldron/idiomatic.js)
- [StandardJS](https://standardjs.com)
@@ -3655,13 +3888,13 @@ Other Style Guides
- [Naming this in nested functions](https://gist.github.com/cjohansen/4135065) - Christian Johansen
- [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) - Ross Allen
- [Popular JavaScript Coding Conventions on GitHub](http://sideeffect.kr/popularconvention/#javascript) - JeongHoon Byun
- - [Multiple var statements in JavaScript, not superfluous](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) - Ben Alman
+ - [Multiple var statements in JavaScript, not superfluous](https://benalman.com/news/2012/05/multiple-var-statements-javascript/) - Ben Alman
**Further Reading**
- [Understanding JavaScript Closures](https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
- - [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
- - [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz
+ - [Basic JavaScript for the impatient programmer](https://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
+ - [You Might Not Need jQuery](https://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz
- [ES6 Features](https://github.com/lukehoban/es6features) - Luke Hoban
- [Frontend Guidelines](https://github.com/bendc/frontend-guidelines) - Benjamin De Cock
@@ -3669,7 +3902,7 @@ Other Style Guides
- [JavaScript: The Good Parts](https://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
- [JavaScript Patterns](https://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
- - [Pro JavaScript Design Patterns](https://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
+ - [Pro JavaScript Design Patterns](https://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
- [High Performance Web Sites: Essential Knowledge for Front-End Engineers](https://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
- [Maintainable JavaScript](https://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
- [JavaScript Web Applications](https://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
@@ -3678,23 +3911,23 @@ Other Style Guides
- [Secrets of the JavaScript Ninja](https://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
- [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
- [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- - [JSBooks](http://jsbooks.revolunet.com/) - Julien Bouquillon
+ - [JSBooks](https://jsbooks.revolunet.com/) - Julien Bouquillon
- [Third Party JavaScript](https://www.manning.com/books/third-party-javascript) - Ben Vinegar and Anton Kovalyov
- - [Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript](http://amzn.com/0321812182) - David Herman
- - [Eloquent JavaScript](http://eloquentjavascript.net/) - Marijn Haverbeke
- - [You Don’t Know JS: ES6 & Beyond](http://shop.oreilly.com/product/0636920033769.do) - Kyle Simpson
+ - [Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript](https://amzn.com/dp/0321812182) - David Herman
+ - [Eloquent JavaScript](https://eloquentjavascript.net/) - Marijn Haverbeke
+ - [You Don’t Know JS: ES6 & Beyond](https://shop.oreilly.com/product/0636920033769.do) - Kyle Simpson
**Blogs**
- - [JavaScript Weekly](http://javascriptweekly.com/)
+ - [JavaScript Weekly](https://javascriptweekly.com/)
- [JavaScript, JavaScript...](https://javascriptweblog.wordpress.com/)
- [Bocoup Weblog](https://bocoup.com/weblog)
- - [Adequately Good](http://www.adequatelygood.com/)
+ - [Adequately Good](https://www.adequatelygood.com/)
- [NCZOnline](https://www.nczonline.net/)
- [Perfection Kills](http://perfectionkills.com/)
- - [Ben Alman](http://benalman.com/)
+ - [Ben Alman](https://benalman.com/)
- [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
- - [nettuts](http://code.tutsplus.com/?s=javascript)
+ - [nettuts](https://code.tutsplus.com/?s=javascript)
**Podcasts**
@@ -3708,37 +3941,32 @@ Other Style Guides
This is a list of organizations that are using this style guide. Send us a pull request and we'll add you to the list.
- **123erfasst**: [123erfasst/javascript](https://github.com/123erfasst/javascript)
- - **3blades**: [3Blades](https://github.com/3blades)
- **4Catalyzer**: [4Catalyzer/javascript](https://github.com/4Catalyzer/javascript)
- **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript)
- - **Adult Swim**: [adult-swim/javascript](https://github.com/adult-swim/javascript)
- **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
+ - **AloPeyk**: [AloPeyk](https://github.com/AloPeyk)
- **AltSchool**: [AltSchool/javascript](https://github.com/AltSchool/javascript)
- **Apartmint**: [apartmint/javascript](https://github.com/apartmint/javascript)
- **Ascribe**: [ascribe/javascript](https://github.com/ascribe/javascript)
- - **Avalara**: [avalara/javascript](https://github.com/avalara/javascript)
- **Avant**: [avantcredit/javascript](https://github.com/avantcredit/javascript)
- **Axept**: [axept/javascript](https://github.com/axept/javascript)
- - **BashPros**: [BashPros/javascript](https://github.com/BashPros/javascript)
- **Billabong**: [billabong/javascript](https://github.com/billabong/javascript)
- **Bisk**: [bisk](https://github.com/Bisk/)
- - **Bonhomme**: [bonhommeparis/javascript](https://github.com/bonhommeparis/javascript)
- **Brainshark**: [brainshark/javascript](https://github.com/brainshark/javascript)
- **CaseNine**: [CaseNine/javascript](https://github.com/CaseNine/javascript)
- **Cerner**: [Cerner](https://github.com/cerner/)
- **Chartboost**: [ChartBoost/javascript-style-guide](https://github.com/ChartBoost/javascript-style-guide)
+ - **Coeur d'Alene Tribe**: [www.cdatribe-nsn.gov](https://www.cdatribe-nsn.gov)
- **ComparaOnline**: [comparaonline/javascript](https://github.com/comparaonline/javascript-style-guide)
- **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
- **DailyMotion**: [dailymotion/javascript](https://github.com/dailymotion/javascript)
- **DoSomething**: [DoSomething/eslint-config](https://github.com/DoSomething/eslint-config)
- **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript)
- - **Drupal**: [www.drupal.org](https://www.drupal.org/project/drupal)
+ - **Drupal**: [www.drupal.org](https://git.drupalcode.org/project/drupal/blob/8.6.x/core/.eslintrc.json)
- **Ecosia**: [ecosia/javascript](https://github.com/ecosia/javascript)
- - **Evernote**: [evernote/javascript-style-guide](https://github.com/evernote/javascript-style-guide)
- **Evolution Gaming**: [evolution-gaming/javascript](https://github.com/evolution-gaming/javascript)
- **EvozonJs**: [evozonjs/javascript](https://github.com/evozonjs/javascript)
- **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
- - **Expensify** [Expensify/Style-Guide](https://github.com/Expensify/Style-Guide/blob/master/javascript.md)
- **Flexberry**: [Flexberry/javascript-style-guide](https://github.com/Flexberry/javascript-style-guide)
- **Gawker Media**: [gawkermedia](https://github.com/gawkermedia/)
- **General Electric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
@@ -3747,14 +3975,13 @@ Other Style Guides
- **GreenChef**: [greenchef/javascript](https://github.com/greenchef/javascript)
- **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
- **Grupo-Abraxas**: [Grupo-Abraxas/javascript](https://github.com/Grupo-Abraxas/javascript)
- - **Honey**: [honeyscience/javascript](https://github.com/honeyscience/javascript)
+ - **Happeo**: [happeo/javascript](https://github.com/happeo/javascript)
- **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript-style-guide)
- - **Huballin**: [huballin](https://github.com/huballin/)
- **HubSpot**: [HubSpot/javascript](https://github.com/HubSpot/javascript)
- **Hyper**: [hyperoslo/javascript-playbook](https://github.com/hyperoslo/javascript-playbook/blob/master/style.md)
+ - **ILIAS**: [ILIAS](https://github.com/ILIAS-eLearning/ILIAS)
- **InterCity Group**: [intercitygroup/javascript-style-guide](https://github.com/intercitygroup/javascript-style-guide)
- **Jam3**: [Jam3/Javascript-Code-Conventions](https://github.com/Jam3/Javascript-Code-Conventions)
- - **JeopardyBot**: [kesne/jeopardy-bot](https://github.com/kesne/jeopardy-bot/blob/master/STYLEGUIDE.md)
- **JSSolutions**: [JSSolutions/javascript](https://github.com/JSSolutions/javascript)
- **Kaplan Komputing**: [kaplankomputing/javascript](https://github.com/kaplankomputing/javascript)
- **KickorStick**: [kickorstick](https://github.com/kickorstick/)
@@ -3765,25 +3992,18 @@ Other Style Guides
- **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript)
- **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
- **MitocGroup**: [MitocGroup/javascript](https://github.com/MitocGroup/javascript)
- - **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
- - **Money Advice Service**: [moneyadviceservice/javascript](https://github.com/moneyadviceservice/javascript)
- **Muber**: [muber](https://github.com/muber/)
- - **National Geographic**: [natgeo](https://github.com/natgeo/)
- - **Nimbl3**: [nimbl3/javascript](https://github.com/nimbl3/javascript)
+ - **National Geographic Society**: [natgeosociety](https://github.com/natgeosociety/)
+ - **NullDev**: [NullDevCo/JavaScript-Styleguide](https://github.com/NullDevCo/JavaScript-Styleguide)
- **Nulogy**: [nulogy/javascript](https://github.com/nulogy/javascript)
- **Orange Hill Development**: [orangehill/javascript](https://github.com/orangehill/javascript)
- **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript)
- - **OutBoxSoft**: [OutBoxSoft/javascript](https://github.com/OutBoxSoft/javascript)
- **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript)
- **Pier 1**: [Pier1/javascript](https://github.com/pier1/javascript)
- **Qotto**: [Qotto/javascript-style-guide](https://github.com/Qotto/javascript-style-guide)
- - **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
- - **reddit**: [reddit/styleguide/javascript](https://github.com/reddit/styleguide/tree/master/javascript)
- - **React**: [facebook.github.io/react/contributing/how-to-contribute.html#style-guide](https://facebook.github.io/react/contributing/how-to-contribute.html#style-guide)
- - **REI**: [reidev/js-style-guide](https://github.com/rei/code-style-guides/)
+ - **React**: [reactjs.org/docs/how-to-contribute.html#style-guide](https://reactjs.org/docs/how-to-contribute.html#style-guide)
- **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide)
- **Sainsbury’s Supermarkets**: [jsainsburyplc](https://github.com/jsainsburyplc)
- - **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide)
- **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
- **Sourcetoad**: [sourcetoad/javascript](https://github.com/sourcetoad/javascript)
- **Springload**: [springload](https://github.com/springload/)
@@ -3794,13 +4014,18 @@ Other Style Guides
- **SysGarage**: [sysgarage/javascript-style-guide](https://github.com/sysgarage/javascript-style-guide)
- **Syzygy Warsaw**: [syzygypl/javascript](https://github.com/syzygypl/javascript)
- **Target**: [target/javascript](https://github.com/target/javascript)
+ - **Terra**: [terra](https://github.com/cerner?utf8=%E2%9C%93&q=terra&type=&language=)
- **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript)
- **The Nerdery**: [thenerdery/javascript-standards](https://github.com/thenerdery/javascript-standards)
+ - **Tomify**: [tomprats](https://github.com/tomprats)
+ - **Traitify**: [traitify/eslint-config-traitify](https://github.com/traitify/eslint-config-traitify)
- **T4R Technology**: [T4R-Technology/javascript](https://github.com/T4R-Technology/javascript)
+ - **UrbanSim**: [urbansim](https://github.com/urbansim/)
- **VoxFeed**: [VoxFeed/javascript-style-guide](https://github.com/VoxFeed/javascript-style-guide)
- **WeBox Studio**: [weboxstudio/javascript](https://github.com/weboxstudio/javascript)
- **Weggo**: [Weggo/javascript](https://github.com/Weggo/javascript)
- **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
+ - **Zit Software**: [zit-software/javascript](https://github.com/zit-software/javascript)
- **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
**[⬆ back to top](#table-of-contents)**
@@ -3824,7 +4049,7 @@ Other Style Guides
-  **Thai**: [lvarayut/javascript-style-guide](https://github.com/lvarayut/javascript-style-guide)
-  **Turkish**: [eraycetinay/javascript](https://github.com/eraycetinay/javascript)
-  **Ukrainian**: [ivanzusko/javascript](https://github.com/ivanzusko/javascript)
- -  **Vietnam**: [hngiang/javascript-style-guide](https://github.com/hngiang/javascript-style-guide)
+ -  **Vietnam**: [dangkyokhoang/javascript-style-guide](https://github.com/dangkyokhoang/javascript-style-guide)
## The JavaScript Style Guide Guide
diff --git a/css-in-javascript/README.md b/css-in-javascript/README.md
index d6162df55d..2e6ab68a1b 100644
--- a/css-in-javascript/README.md
+++ b/css-in-javascript/README.md
@@ -34,7 +34,7 @@
- Use an underscore for modifiers to other styles.
- > Why? Similar to BEM, this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes.
+ > Why? Similar to [BEM](https://getbem.com/introduction/), this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes.
```js
// bad
diff --git a/linters/.markdownlint.json b/linters/.markdownlint.json
index 594886042d..951337dbc5 100644
--- a/linters/.markdownlint.json
+++ b/linters/.markdownlint.json
@@ -26,7 +26,8 @@
"comment": "MD007: Unordered list indentation: 2 spaces.",
"ul-indent": {
- "indent": 2
+ "indent": 2,
+ "start_indented": true
},
"comment": "MD009: Disallow trailing spaces!",
@@ -68,7 +69,7 @@
"no-multiple-space-closed-atx": true,
"comment": "MD022: Headers should be surrounded by blank lines.",
- "comment": "Some headers have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers",
+ "comment": "Some headers have preceding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers",
"blanks-around-headers": false,
"comment": "MD023: Headers must start at the beginning of the line.",
@@ -110,7 +111,7 @@
"blanks-around-fences": true,
"comment": "MD032: Lists should be surrounded by blank lines",
- "comment": "Some lists have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers",
+ "comment": "Some lists have preceding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers",
"blanks-around-lists": false,
"comment": "MD033: Disallow inline HTML",
diff --git a/linters/SublimeLinter/SublimeLinter.sublime-settings b/linters/SublimeLinter/SublimeLinter.sublime-settings
index 259dbaff6a..7ce44c9821 100644
--- a/linters/SublimeLinter/SublimeLinter.sublime-settings
+++ b/linters/SublimeLinter/SublimeLinter.sublime-settings
@@ -9,7 +9,7 @@
*
* @version 0.3.0
* @see https://github.com/SublimeLinter/SublimeLinter
- * @see http://www.jshint.com/docs/
+ * @see https://www.jshint.com/docs/
*/
{
"jshint_options":
diff --git a/package.json b/package.json
index 1fdcd7be15..a78bc250d4 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"description": "A mostly reasonable approach to JavaScript.",
"scripts": {
"preinstall": "npm run install:config && npm run install:config:base",
+ "postinstall": "rm -rf node_modules/markdownlint-cli/node_modules/markdownlint",
"install:config": "cd packages/eslint-config-airbnb && npm prune && npm install",
"install:config:base": "cd packages/eslint-config-airbnb-base && npm prune && npm install",
"lint": "markdownlint --config linters/.markdownlint.json README.md */README.md",
@@ -39,6 +40,7 @@
},
"homepage": "https://github.com/airbnb/javascript",
"devDependencies": {
- "markdownlint-cli": "^0.10.0"
+ "markdownlint": "^0.29.0",
+ "markdownlint-cli": "^0.35.0"
}
}
diff --git a/packages/eslint-config-airbnb-base/.eslintrc b/packages/eslint-config-airbnb-base/.eslintrc
index f9bd289286..7606a50a46 100644
--- a/packages/eslint-config-airbnb-base/.eslintrc
+++ b/packages/eslint-config-airbnb-base/.eslintrc
@@ -4,7 +4,7 @@
// disable requiring trailing commas because it might be nice to revert to
// being JSON at some point, and I don't want to make big changes now.
"comma-dangle": 0,
- // we support node 4
- "prefer-destructuring": 0,
+
+ "max-len": 0,
},
}
diff --git a/packages/eslint-config-airbnb-base/CHANGELOG.md b/packages/eslint-config-airbnb-base/CHANGELOG.md
index c945013b25..51522a3f4e 100644
--- a/packages/eslint-config-airbnb-base/CHANGELOG.md
+++ b/packages/eslint-config-airbnb-base/CHANGELOG.md
@@ -1,3 +1,91 @@
+15.0.0 / 2021-11-08
+==================
+ - [breaking] drop eslint < 7, add eslint 8 (#2495)
+ - [breaking] add `exports`
+ - [patch] Improve `function-paren-newline` with `multiline-arguments` option (#2471)
+ - [patch] update default value for complexity (#2420)
+ - [patch] add disabled `no-unsafe-optional-chaining` rule
+ - [patch] arthmetic -> arithmetic (#2341)
+ - [patch] fix spelling of "than" (#2333)
+ - [patch] add `no-nonoctal-decimal-escape` rule
+ - [patch] `import/no-extraneous-dependencies`: Add .eslintrc.js to devDeps (#2329)
+ - [guide] Spread operator => Spread syntax (#2423)
+ - [guide] add references for eslint rules (#2419)
+ - [Docs] HTTP => HTTPS (#2489)
+ - [readme] some updates
+ - [meta] use `prepublishOnly` script for npm 7+
+ - [deps] update `eslint-plugin-import`, `eslint-plugin-react`, `object.entries`
+ - [dev deps] update `@babel/runtime`, `tape`
+
+14.2.1 / 2020-11-06
+==================
+ - [base] `no-restricted-globals`: add better messages (#2320)
+ - [base] add new core eslint rules, set to off
+ - [deps] update `confusing-browser-globals`, `object.assign`
+ - [deps] update `eslint-plugin-import`, use valid `import/no-cycle` `maxDepth` option (#2250, #2249)
+ - [dev deps] update `@babel/runtime`, `eslint-find-rules`, `eslint-plugin-import`
+
+14.2.0 / 2020-06-10
+==================
+ - [new] add `eslint` `v7`
+ - [minor] Disallow multiple empty lines (#2238)
+ - [minor] Fix typo in no-multiple-empty-lines rule (#2168)
+ - [patch] Include 'context' exception for `no-param-reassign` (#2230)
+ - [patch] Allow triple-slash (///) comments (#2197)
+ - [patch] Disable `prefer-object-spread` for `airbnb-base/legacy` (#2198)
+ - [deps] update `eslint-plugin-import`, `eslint-plugin-react`, `babel-preset-airbnb`, `eslint-find-rules`, `in-publish`, `tape`, `object.entries`
+
+14.1.0 / 2020-03-12
+==================
+ - [minor] add new disabled rules, update eslint
+ - [minor] enable `import/no-useless-path-segments` for commonjs (#2113)
+ - [fix] `whitespace`: only set erroring rules to "warn"
+ - Fix indentation with JSX Fragments (#2157)
+ - [patch] `import/no-extraneous-dependencies`: Support karma config files (#2121)
+ - [readme] normalize multiline word according to merriam-webster (#2138)
+ - [deps] update `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, `object.entries`, `confusing-browser-globals`
+ - [dev deps] update `@babel/runtime`, `babel-preset-airbnb`, `safe-publish-latest`, `tape`
+ - [tests] re-enable eslint rule `prefer-destructuring` internally (#2110)
+
+14.0.0 / 2019-08-09
+==================
+ - [breaking] `no-self-assign`: enable `props` option
+ - [breaking] enable `no-useless-catch`
+ - [breaking] enable `max-classes-per-file`
+ - [breaking] enable `no-misleading-character-class`
+ - [breaking] enable `no-async-promise-executor`
+ - [breaking] enable `prefer-object-spread`
+ - [breaking] `func-name-matching`: enable `considerPropertyDescriptor` option
+ - [breaking] `padded-blocks`: enable `allowSingleLineBlocks` option (#1255)
+ - [breaking] `no-multiple-empty-lines`: Restrict empty lines at beginning of file (#2042)
+ - [breaking] Set 'strict' to 'never' (#1962)
+ - [breaking] legacy: Enable 'strict' (#1962)
+ - [breaking] Simplifies `no-mixed-operators` (#1864)
+ - [breaking] Require parens for arrow function args (#1863)
+ - [breaking] add eslint v6, drop eslint v4
+ - [patch] `camelcase`: enable ignoreDestructuring
+ - [patch] Add markers to spaced-comment block for Flow types (#1966)
+ - [patch] Do not prefer destructuring for object assignment expression (#1583)
+ - [deps] update `confusing-browser-globals`, `eslint-plugin-import`, `tape`, `babel-preset-airbnb`
+ - [dev deps] update babel-related deps to latest
+ - [dev deps] update `eslint-find-rules`, `eslint-plugin-import`
+ - [tests] only run tests in non-lint per-package travis job
+ - [tests] use `eclint` instead of `editorconfig-tools`
+
+13.2.0 / 2019-07-01
+==================
+ - [minor] Enforce dangling underscores in method names (#1907)
+ - [fix] disable `no-var` in legacy entry point
+ - [patch] Ignore property modifications of `staticContext` params (#2029)
+ - [patch] `no-extraneous-dependencies`: Add jest.setup.js to devDeps (#1998)
+ - [meta] add disabled `prefer-named-capture-group` rule
+ - [meta] add disabled `no-useless-catch` config
+ - [deps] Switch to confusing-browser-globals (#1961)
+ - [deps] update `object.entries`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `tape`
+ - [docs] correct JavaScript capitalization (#2046)
+ - [readme] Improve eslint config setup instructions for yarn (#2001)
+ - [docs] fix docs for whitespace config (#1914, #1871)
+
13.1.0 / 2018-08-13
==================
- [new] add eslint v5 support (#1834)
diff --git a/packages/eslint-config-airbnb-base/README.md b/packages/eslint-config-airbnb-base/README.md
index 3c1a9ce914..6ddc34dac1 100644
--- a/packages/eslint-config-airbnb-base/README.md
+++ b/packages/eslint-config-airbnb-base/README.md
@@ -1,6 +1,10 @@
-# eslint-config-airbnb-base
+# eslint-config-airbnb-base [![Version Badge][npm-version-svg]][package-url]
-[](http://badge.fury.io/js/eslint-config-airbnb-base)
+[][package-url]
+
+[![github actions][actions-image]][actions-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
This package provides Airbnb's base JS .eslintrc (without React plugins) as an extensible shared config.
@@ -12,8 +16,6 @@ We export two ESLint configurations for your usage.
Our default export contains all of our ESLint rules, including ECMAScript 6+. It requires `eslint` and `eslint-plugin-import`.
-If you use yarn, run `npm info "eslint-config-airbnb-base@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. See below for npm instructions.
-
1. Install the correct versions of each package, which are listed by the command:
```sh
@@ -26,6 +28,10 @@ If you use yarn, run `npm info "eslint-config-airbnb-base@latest" peerDependenci
npx install-peerdeps --dev eslint-config-airbnb-base
```
+ If using **yarn**, you can also use the shortcut described above if you have npm 5+ installed on your machine, as the command will detect that you are using yarn and will act accordingly.
+ Otherwise, run `npm info "eslint-config-airbnb-base@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency.
+
+
If using **npm < 5**, Linux/OSX users can run
```sh
@@ -77,16 +83,16 @@ Lints ES5 and below. Requires `eslint` and `eslint-plugin-import`.
Which produces and runs a command like:
```sh
- npm install --save-dev eslint-config-airbnb-base eslint@^3.0.1 eslint-plugin-import@^1.10.3
+ npm install --save-dev eslint-config-airbnb-base eslint@^#.#.# eslint-plugin-import@^#.#.#
```
2. Add `"extends": "airbnb-base/legacy"` to your .eslintrc
-See [Airbnb's overarching ESLint config](https://npmjs.com/eslint-config-airbnb), [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript), and the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information.
+See [Airbnb's overarching ESLint config](https://npmjs.com/eslint-config-airbnb), [Airbnb's JavaScript styleguide](https://github.com/airbnb/javascript), and the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information.
### eslint-config-airbnb-base/whitespace
-This entry point only warns on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/whitespace.js).
+This entry point only errors on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/whitespace.js).
## Improving this config
@@ -95,3 +101,12 @@ Consider adding test cases if you're making complicated rules changes, like anyt
You can run tests with `npm test`.
You can make sure this module lints with itself using `npm run lint`.
+
+[package-url]: https://npmjs.org/package/eslint-config-airbnb-base
+[npm-version-svg]: https://versionbadg.es/airbnb/javascript.svg
+[license-image]: https://img.shields.io/npm/l/eslint-config-airbnb-base.svg
+[license-url]: LICENSE.md
+[downloads-image]: https://img.shields.io/npm/dm/eslint-config-airbnb-base.svg
+[downloads-url]: https://npm-stat.com/charts.html?package=eslint-config-airbnb-base
+[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/airbnb/javascript
+[actions-url]: https://github.com/airbnb/javascript/actions
diff --git a/packages/eslint-config-airbnb-base/index.js b/packages/eslint-config-airbnb-base/index.js
index 16b423f35d..825456b8a4 100644
--- a/packages/eslint-config-airbnb-base/index.js
+++ b/packages/eslint-config-airbnb-base/index.js
@@ -7,12 +7,11 @@ module.exports = {
'./rules/variables',
'./rules/es6',
'./rules/imports',
+ './rules/strict',
].map(require.resolve),
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
- rules: {
- strict: 'error',
- },
+ rules: {},
};
diff --git a/packages/eslint-config-airbnb-base/legacy.js b/packages/eslint-config-airbnb-base/legacy.js
index 7cc2441ab3..e5c9089c75 100644
--- a/packages/eslint-config-airbnb-base/legacy.js
+++ b/packages/eslint-config-airbnb-base/legacy.js
@@ -27,5 +27,8 @@ module.exports = {
property: '__defineSetter__',
message: 'Please use Object.defineProperty instead.',
}],
+ 'no-var': 'off',
+ 'prefer-object-spread': 'off',
+ strict: ['error', 'safe'],
}
};
diff --git a/packages/eslint-config-airbnb-base/package.json b/packages/eslint-config-airbnb-base/package.json
index 91bcb47195..8f039d4d7c 100644
--- a/packages/eslint-config-airbnb-base/package.json
+++ b/packages/eslint-config-airbnb-base/package.json
@@ -1,18 +1,33 @@
{
"name": "eslint-config-airbnb-base",
- "version": "13.1.0",
+ "version": "15.0.0",
"description": "Airbnb's base JS ESLint config, following our styleguide",
"main": "index.js",
+ "exports": {
+ ".": "./index.js",
+ "./legacy": "./legacy.js",
+ "./whitespace": "./whitespace.js",
+ "./rules/best-practices": "./rules/best-practices.js",
+ "./rules/es6": "./rules/es6.js",
+ "./rules/node": "./rules/node.js",
+ "./rules/style": "./rules/style.js",
+ "./rules/errors": "./rules/errors.js",
+ "./rules/imports": "./rules/imports.js",
+ "./rules/strict": "./rules/strict.js",
+ "./rules/variables": "./rules/variables.js",
+ "./package.json": "./package.json"
+ },
"scripts": {
- "prelint": "editorconfig-tools check * rules/* test/*",
+ "prelint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
"lint": "eslint --report-unused-disable-directives .",
"pretests-only": "node ./test/requires",
"tests-only": "babel-tape-runner ./test/test-*.js",
- "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest",
+ "prepublishOnly": "eslint-find-rules --unused && npm test && safe-publish-latest",
+ "prepublish": "not-in-publish || npm run prepublishOnly",
"pretest": "npm run --silent lint",
"test": "npm run --silent tests-only",
"pretravis": ":",
- "travis": "npm run --silent test",
+ "travis": "npm run --silent tests-only",
"posttravis": ":"
},
"repository": {
@@ -53,26 +68,25 @@
},
"homepage": "https://github.com/airbnb/javascript",
"devDependencies": {
- "babel-preset-airbnb": "^2.5.3",
- "babel-tape-runner": "^2.0.1",
- "editorconfig-tools": "^0.1.1",
- "eslint": "^4.19.1 || ^5.3.0",
- "eslint-find-rules": "^3.3.1",
- "eslint-plugin-import": "^2.14.0",
- "in-publish": "^2.0.0",
- "safe-publish-latest": "^1.1.2",
- "tape": "^4.9.1"
+ "@babel/runtime": "^7.25.6",
+ "babel-preset-airbnb": "^4.5.0",
+ "babel-tape-runner": "^3.0.0",
+ "eclint": "^2.8.1",
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-find-rules": "^4.1.0",
+ "eslint-plugin-import": "^2.30.0",
+ "in-publish": "^2.0.1",
+ "safe-publish-latest": "^2.0.0",
+ "tape": "^5.9.0"
},
"peerDependencies": {
- "eslint": "^4.19.1 || ^5.3.0",
- "eslint-plugin-import": "^2.14.0"
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.30.0"
},
"engines": {
- "node": ">= 4"
+ "node": "^10.12.0 || >=12.0.0"
},
"dependencies": {
- "eslint-restricted-globals": "^0.1.1",
- "object.assign": "^4.1.0",
- "object.entries": "^1.0.4"
+ "confusing-browser-globals": "^1.0.11"
}
}
diff --git a/packages/eslint-config-airbnb-base/rules/best-practices.js b/packages/eslint-config-airbnb-base/rules/best-practices.js
index fbd65cf7d3..09c247451a 100644
--- a/packages/eslint-config-airbnb-base/rules/best-practices.js
+++ b/packages/eslint-config-airbnb-base/rules/best-practices.js
@@ -1,6 +1,7 @@
module.exports = {
rules: {
// enforces getter/setter pairs in objects
+ // https://eslint.org/docs/rules/accessor-pairs
'accessor-pairs': 'off',
// enforces return statements in callbacks of array's methods
@@ -8,10 +9,12 @@ module.exports = {
'array-callback-return': ['error', { allowImplicit: true }],
// treat var statements as if they were block scoped
+ // https://eslint.org/docs/rules/block-scoped-var
'block-scoped-var': 'error',
// specify the maximum cyclomatic complexity allowed in a program
- complexity: ['off', 11],
+ // https://eslint.org/docs/rules/complexity
+ complexity: ['off', 20],
// enforce that class methods use "this"
// https://eslint.org/docs/rules/class-methods-use-this
@@ -20,15 +23,26 @@ module.exports = {
}],
// require return statements to either always or never specify values
+ // https://eslint.org/docs/rules/consistent-return
'consistent-return': 'error',
// specify curly brace conventions for all control statements
- curly: ['error', 'multi-line'],
+ // https://eslint.org/docs/rules/curly
+ curly: ['error', 'multi-line'], // multiline
// require default case in switch statements
+ // https://eslint.org/docs/rules/default-case
'default-case': ['error', { commentPattern: '^no default$' }],
+ // Enforce default clauses in switch statements to be last
+ // https://eslint.org/docs/rules/default-case-last
+ 'default-case-last': 'error',
+
+ // https://eslint.org/docs/rules/default-param-last
+ 'default-param-last': 'error',
+
// encourages use of dot notation whenever possible
+ // https://eslint.org/docs/rules/dot-notation
'dot-notation': ['error', { allowKeywords: true }],
// enforces consistent newlines before or after dots
@@ -39,24 +53,35 @@ module.exports = {
// https://eslint.org/docs/rules/eqeqeq
eqeqeq: ['error', 'always', { null: 'ignore' }],
+ // Require grouped accessor pairs in object literals and classes
+ // https://eslint.org/docs/rules/grouped-accessor-pairs
+ 'grouped-accessor-pairs': 'error',
+
// make sure for-in loops have an if statement
+ // https://eslint.org/docs/rules/guard-for-in
'guard-for-in': 'error',
// enforce a maximum number of classes per file
// https://eslint.org/docs/rules/max-classes-per-file
- // TODO: semver-major (eslint 5): enable
- 'max-classes-per-file': ['off', 1],
+ 'max-classes-per-file': ['error', 1],
// disallow the use of alert, confirm, and prompt
+ // https://eslint.org/docs/rules/no-alert
+ // TODO: enable, semver-major
'no-alert': 'warn',
// disallow use of arguments.caller or arguments.callee
+ // https://eslint.org/docs/rules/no-caller
'no-caller': 'error',
// disallow lexical declarations in case/default clauses
- // https://eslint.org/docs/rules/no-case-declarations.html
+ // https://eslint.org/docs/rules/no-case-declarations
'no-case-declarations': 'error',
+ // Disallow returning value in constructor
+ // https://eslint.org/docs/rules/no-constructor-return
+ 'no-constructor-return': 'error',
+
// disallow division operators explicitly at beginning of regular expression
// https://eslint.org/docs/rules/no-div-regex
'no-div-regex': 'off',
@@ -79,16 +104,25 @@ module.exports = {
// https://eslint.org/docs/rules/no-empty-pattern
'no-empty-pattern': 'error',
+ // Disallow empty static blocks
+ // https://eslint.org/docs/latest/rules/no-empty-static-block
+ // TODO: semver-major, enable
+ 'no-empty-static-block': 'off',
+
// disallow comparisons to null without a type-checking operator
+ // https://eslint.org/docs/rules/no-eq-null
'no-eq-null': 'off',
// disallow use of eval()
+ // https://eslint.org/docs/rules/no-eval
'no-eval': 'error',
// disallow adding to native types
+ // https://eslint.org/docs/rules/no-extend-native
'no-extend-native': 'error',
// disallow unnecessary function binding
+ // https://eslint.org/docs/rules/no-extra-bind
'no-extra-bind': 'error',
// disallow Unnecessary Labels
@@ -96,15 +130,19 @@ module.exports = {
'no-extra-label': 'error',
// disallow fallthrough of case statements
+ // https://eslint.org/docs/rules/no-fallthrough
'no-fallthrough': 'error',
// disallow the use of leading or trailing decimal points in numeric literals
+ // https://eslint.org/docs/rules/no-floating-decimal
'no-floating-decimal': 'error',
// disallow reassignments of native objects or read-only globals
// https://eslint.org/docs/rules/no-global-assign
'no-global-assign': ['error', { exceptions: [] }],
+
// deprecated in favor of no-global-assign
+ // https://eslint.org/docs/rules/no-native-reassign
'no-native-reassign': 'off',
// disallow implicit type conversions
@@ -121,21 +159,27 @@ module.exports = {
'no-implicit-globals': 'off',
// disallow use of eval()-like methods
+ // https://eslint.org/docs/rules/no-implied-eval
'no-implied-eval': 'error',
// disallow this keywords outside of classes or class-like objects
+ // https://eslint.org/docs/rules/no-invalid-this
'no-invalid-this': 'off',
// disallow usage of __iterator__ property
+ // https://eslint.org/docs/rules/no-iterator
'no-iterator': 'error',
- // disallow use of labels for anything other then loops and switches
+ // disallow use of labels for anything other than loops and switches
+ // https://eslint.org/docs/rules/no-labels
'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
// disallow unnecessary nested blocks
+ // https://eslint.org/docs/rules/no-lone-blocks
'no-lone-blocks': 'error',
// disallow creation of functions within loops
+ // https://eslint.org/docs/rules/no-loop-func
'no-loop-func': 'error',
// disallow magic numbers
@@ -148,27 +192,43 @@ module.exports = {
}],
// disallow use of multiple spaces
+ // https://eslint.org/docs/rules/no-multi-spaces
'no-multi-spaces': ['error', {
ignoreEOLComments: false,
}],
// disallow use of multiline strings
+ // https://eslint.org/docs/rules/no-multi-str
'no-multi-str': 'error',
// disallow use of new operator when not part of the assignment or comparison
+ // https://eslint.org/docs/rules/no-new
'no-new': 'error',
// disallow use of new operator for Function object
+ // https://eslint.org/docs/rules/no-new-func
'no-new-func': 'error',
// disallows creating new instances of String, Number, and Boolean
+ // https://eslint.org/docs/rules/no-new-wrappers
'no-new-wrappers': 'error',
+ // Disallow \8 and \9 escape sequences in string literals
+ // https://eslint.org/docs/rules/no-nonoctal-decimal-escape
+ 'no-nonoctal-decimal-escape': 'error',
+
+ // Disallow calls to the Object constructor without an argument
+ // https://eslint.org/docs/latest/rules/no-object-constructor
+ // TODO: enable, semver-major
+ 'no-object-constructor': 'off',
+
// disallow use of (old style) octal literals
+ // https://eslint.org/docs/rules/no-octal
'no-octal': 'error',
// disallow use of octal escape sequences in string literals, such as
// var foo = 'Copyright \251';
+ // https://eslint.org/docs/rules/no-octal-escape
'no-octal-escape': 'error',
// disallow reassignment of function parameters
@@ -181,18 +241,22 @@ module.exports = {
'accumulator', // for reduce accumulators
'e', // for e.returnvalue
'ctx', // for Koa routing
+ 'context', // for Koa routing
'req', // for Express requests
'request', // for Express requests
'res', // for Express responses
'response', // for Express responses
'$scope', // for Angular 1 scopes
+ 'staticContext', // for ReactRouter context
]
}],
// disallow usage of __proto__ property
+ // https://eslint.org/docs/rules/no-proto
'no-proto': 'error',
- // disallow declaring the same variable more then once
+ // disallow declaring the same variable more than once
+ // https://eslint.org/docs/rules/no-redeclare
'no-redeclare': 'error',
// disallow certain object properties
@@ -238,28 +302,33 @@ module.exports = {
}],
// disallow use of assignment in return statement
+ // https://eslint.org/docs/rules/no-return-assign
'no-return-assign': ['error', 'always'],
// disallow redundant `return await`
+ // https://eslint.org/docs/rules/no-return-await
'no-return-await': 'error',
// disallow use of `javascript:` urls.
+ // https://eslint.org/docs/rules/no-script-url
'no-script-url': 'error',
// disallow self assignment
// https://eslint.org/docs/rules/no-self-assign
- // TODO: semver-major: props -> true
'no-self-assign': ['error', {
- props: false,
+ props: true,
}],
// disallow comparisons where both sides are exactly the same
+ // https://eslint.org/docs/rules/no-self-compare
'no-self-compare': 'error',
// disallow use of comma operator
+ // https://eslint.org/docs/rules/no-sequences
'no-sequences': 'error',
// restrict what can be thrown as an exception
+ // https://eslint.org/docs/rules/no-throw-literal
'no-throw-literal': 'error',
// disallow unmodified conditions of loops
@@ -267,6 +336,7 @@ module.exports = {
'no-unmodified-loop-condition': 'off',
// disallow usage of expressions in statement position
+ // https://eslint.org/docs/rules/no-unused-expressions
'no-unused-expressions': ['error', {
allowShortCircuit: false,
allowTernary: false,
@@ -278,8 +348,13 @@ module.exports = {
'no-unused-labels': 'error',
// disallow unnecessary .call() and .apply()
+ // https://eslint.org/docs/rules/no-useless-call
'no-useless-call': 'off',
+ // Disallow unnecessary catch clauses
+ // https://eslint.org/docs/rules/no-useless-catch
+ 'no-useless-catch': 'error',
+
// disallow useless string concatenation
// https://eslint.org/docs/rules/no-useless-concat
'no-useless-concat': 'error',
@@ -297,16 +372,33 @@ module.exports = {
'no-void': 'error',
// disallow usage of configurable warning terms in comments: e.g. todo
+ // https://eslint.org/docs/rules/no-warning-comments
'no-warning-comments': ['off', { terms: ['todo', 'fixme', 'xxx'], location: 'start' }],
// disallow use of the with statement
+ // https://eslint.org/docs/rules/no-with
'no-with': 'error',
// require using Error objects as Promise rejection reasons
// https://eslint.org/docs/rules/prefer-promise-reject-errors
'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }],
+ // Suggest using named capture group in regular expression
+ // https://eslint.org/docs/rules/prefer-named-capture-group
+ 'prefer-named-capture-group': 'off',
+
+ // Prefer Object.hasOwn() over Object.prototype.hasOwnProperty.call()
+ // https://eslint.org/docs/rules/prefer-object-has-own
+ // TODO: semver-major: enable thus rule, once eslint v8.5.0 is required
+ 'prefer-object-has-own': 'off',
+
+ // https://eslint.org/docs/rules/prefer-regex-literals
+ 'prefer-regex-literals': ['error', {
+ disallowRedundantWrapping: true,
+ }],
+
// require use of the second argument for parseInt()
+ // https://eslint.org/docs/rules/radix
radix: 'error',
// require `await` in `async function` (note: this is a horrible rule that should never be used)
@@ -318,6 +410,7 @@ module.exports = {
'require-unicode-regexp': 'off',
// requires to declare all vars on top of their containing scope
+ // https://eslint.org/docs/rules/vars-on-top
'vars-on-top': 'error',
// require immediate function invocation to be wrapped in parentheses
@@ -325,6 +418,7 @@ module.exports = {
'wrap-iife': ['error', 'outside', { functionPrototypeMethods: false }],
// require or disallow Yoda conditions
+ // https://eslint.org/docs/rules/yoda
yoda: 'error'
}
};
diff --git a/packages/eslint-config-airbnb-base/rules/errors.js b/packages/eslint-config-airbnb-base/rules/errors.js
index aca6d7d9c3..a3dda4e510 100644
--- a/packages/eslint-config-airbnb-base/rules/errors.js
+++ b/packages/eslint-config-airbnb-base/rules/errors.js
@@ -10,8 +10,7 @@ module.exports = {
// disallow using an async function as a Promise executor
// https://eslint.org/docs/rules/no-async-promise-executor
- // TODO: enable, semver-major
- 'no-async-promise-executor': 'off',
+ 'no-async-promise-executor': 'error',
// Disallow await inside of loops
// https://eslint.org/docs/rules/no-await-in-loop
@@ -27,6 +26,11 @@ module.exports = {
// disallow use of console
'no-console': 'warn',
+ // Disallows expressions where the operation doesn't affect the value
+ // https://eslint.org/docs/rules/no-constant-binary-expression
+ // TODO: semver-major, enable
+ 'no-constant-binary-expression': 'off',
+
// disallow use of constant expressions in conditions
'no-constant-condition': 'warn',
@@ -39,6 +43,10 @@ module.exports = {
// disallow duplicate arguments in functions
'no-dupe-args': 'error',
+ // Disallow duplicate conditions in if-else-if chains
+ // https://eslint.org/docs/rules/no-dupe-else-if
+ 'no-dupe-else-if': 'error',
+
// disallow duplicate keys when creating object literals
'no-dupe-keys': 'error',
@@ -74,6 +82,9 @@ module.exports = {
// disallow overwriting functions written as function declarations
'no-func-assign': 'error',
+ // https://eslint.org/docs/rules/no-import-assign
+ 'no-import-assign': 'error',
+
// disallow function or variable declarations in nested blocks
'no-inner-declarations': 'error',
@@ -83,14 +94,26 @@ module.exports = {
// disallow irregular whitespace outside of strings and comments
'no-irregular-whitespace': 'error',
+ // Disallow Number Literals That Lose Precision
+ // https://eslint.org/docs/rules/no-loss-of-precision
+ 'no-loss-of-precision': 'error',
+
// Disallow characters which are made with multiple code points in character class syntax
// https://eslint.org/docs/rules/no-misleading-character-class
- // TODO: enable, semver-major
- 'no-misleading-character-class': 'off',
+ 'no-misleading-character-class': 'error',
// disallow the use of object properties of the global object (Math and JSON) as functions
'no-obj-calls': 'error',
+ // Disallow new operators with global non-constructor functions
+ // https://eslint.org/docs/latest/rules/no-new-native-nonconstructor
+ // TODO: semver-major, enable
+ 'no-new-native-nonconstructor': 'off',
+
+ // Disallow returning values from Promise executor functions
+ // https://eslint.org/docs/rules/no-promise-executor-return
+ 'no-promise-executor-return': 'error',
+
// disallow use of Object.prototypes builtins directly
// https://eslint.org/docs/rules/no-prototype-builtins
'no-prototype-builtins': 'error',
@@ -98,6 +121,10 @@ module.exports = {
// disallow multiple spaces in a regular expression literal
'no-regex-spaces': 'error',
+ // Disallow returning values from setters
+ // https://eslint.org/docs/rules/no-setter-return
+ 'no-setter-return': 'error',
+
// disallow sparse arrays
'no-sparse-arrays': 'error',
@@ -112,6 +139,12 @@ module.exports = {
// disallow unreachable statements after a return, throw, continue, or break statement
'no-unreachable': 'error',
+ // Disallow loops with a body that allows only one iteration
+ // https://eslint.org/docs/rules/no-unreachable-loop
+ 'no-unreachable-loop': ['error', {
+ ignore: [], // WhileStatement, DoWhileStatement, ForStatement, ForInStatement, ForOfStatement
+ }],
+
// disallow return/throw/break/continue inside finally blocks
// https://eslint.org/docs/rules/no-unsafe-finally
'no-unsafe-finally': 'error',
@@ -119,13 +152,27 @@ module.exports = {
// disallow negating the left operand of relational operators
// https://eslint.org/docs/rules/no-unsafe-negation
'no-unsafe-negation': 'error',
+
+ // disallow use of optional chaining in contexts where the undefined value is not allowed
+ // https://eslint.org/docs/rules/no-unsafe-optional-chaining
+ 'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }],
+
+ // Disallow Unused Private Class Members
+ // https://eslint.org/docs/rules/no-unused-private-class-members
+ // TODO: enable once eslint 7 is dropped (which is semver-major)
+ 'no-unused-private-class-members': 'off',
+
+ // Disallow useless backreferences in regular expressions
+ // https://eslint.org/docs/rules/no-useless-backreference
+ 'no-useless-backreference': 'error',
+
// disallow negation of the left operand of an in expression
// deprecated in favor of no-unsafe-negation
'no-negated-in-lhs': 'off',
// Disallow assignments that can lead to race conditions due to usage of await or yield
// https://eslint.org/docs/rules/require-atomic-updates
- // TODO: enable, semver-major
+ // note: not enabled because it is very buggy
'require-atomic-updates': 'off',
// disallow comparisons with the value NaN
diff --git a/packages/eslint-config-airbnb-base/rules/es6.js b/packages/eslint-config-airbnb-base/rules/es6.js
index f9e5198c96..5e59cbebf4 100644
--- a/packages/eslint-config-airbnb-base/rules/es6.js
+++ b/packages/eslint-config-airbnb-base/rules/es6.js
@@ -21,9 +21,7 @@ module.exports = {
// require parens in arrow function arguments
// https://eslint.org/docs/rules/arrow-parens
- 'arrow-parens': ['error', 'as-needed', {
- requireForBlockBody: true,
- }],
+ 'arrow-parens': ['error', 'always'],
// require space before/after arrow function's arrow
// https://eslint.org/docs/rules/arrow-spacing
@@ -55,13 +53,22 @@ module.exports = {
// disallow importing from the same path more than once
// https://eslint.org/docs/rules/no-duplicate-imports
- // replaced by https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
+ // replaced by https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
'no-duplicate-imports': 'off',
// disallow symbol constructor
// https://eslint.org/docs/rules/no-new-symbol
'no-new-symbol': 'error',
+ // Disallow specified names in exports
+ // https://eslint.org/docs/rules/no-restricted-exports
+ 'no-restricted-exports': ['error', {
+ restrictedNamedExports: [
+ 'default', // use `export default` to provide a default export
+ 'then', // this will cause tons of confusion when your module is dynamically `import()`ed, and will break in most node ESM versions
+ ],
+ }],
+
// disallow specific imports
// https://eslint.org/docs/rules/no-restricted-imports
'no-restricted-imports': ['off', {
@@ -120,7 +127,7 @@ module.exports = {
},
AssignmentExpression: {
array: true,
- object: true,
+ object: false,
},
}, {
enforceForRenamedProperties: false,
@@ -138,7 +145,7 @@ module.exports = {
// https://eslint.org/docs/rules/prefer-rest-params
'prefer-rest-params': 'error',
- // suggest using the spread operator instead of .apply()
+ // suggest using the spread syntax instead of .apply()
// https://eslint.org/docs/rules/prefer-spread
'prefer-spread': 'error',
@@ -158,6 +165,7 @@ module.exports = {
// https://eslint.org/docs/rules/sort-imports
'sort-imports': ['off', {
ignoreCase: false,
+ ignoreDeclarationSort: false,
ignoreMemberSort: false,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
}],
diff --git a/packages/eslint-config-airbnb-base/rules/imports.js b/packages/eslint-config-airbnb-base/rules/imports.js
index fbeca8dc83..d36e4908fa 100644
--- a/packages/eslint-config-airbnb-base/rules/imports.js
+++ b/packages/eslint-config-airbnb-base/rules/imports.js
@@ -33,40 +33,40 @@ module.exports = {
// Static analysis:
// ensure imports point to files/modules that can be resolved
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md
'import/no-unresolved': ['error', { commonjs: true, caseSensitive: true }],
// ensure named imports coupled with named exports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it
'import/named': 'error',
// ensure default import coupled with default export
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it
'import/default': 'off',
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/namespace.md
'import/namespace': 'off',
// Helpful warnings:
// disallow invalid exports, e.g. multiple defaults
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/export.md
'import/export': 'error',
// do not allow a default import name to match a named export
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md
'import/no-named-as-default': 'error',
// warn on accessing default export property names that are also named exports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md
'import/no-named-as-default-member': 'error',
// disallow use of jsdoc-marked-deprecated imports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md
'import/no-deprecated': 'off',
// Forbid the use of extraneous packages
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
// paths are treated both as absolute paths, and relative to process.cwd()
'import/no-extraneous-dependencies': ['error', {
devDependencies: [
@@ -79,6 +79,7 @@ module.exports = {
'test-*.{js,jsx}', // repos with multiple top-level test files
'**/*{.,_}{test,spec}.{js,jsx}', // tests where the extension or filename suffix denotes that it is a test
'**/jest.config.js', // jest config
+ '**/jest.setup.js', // jest setup
'**/vue.config.js', // vue-cli config
'**/webpack.config.js', // webpack config
'**/webpack.config.*.js', // webpack config
@@ -89,51 +90,53 @@ module.exports = {
'**/Gruntfile{,.js}', // grunt config
'**/protractor.conf.js', // protractor config
'**/protractor.conf.*.js', // protractor config
+ '**/karma.conf.js', // karma config
+ '**/.eslintrc.js' // eslint config
],
optionalDependencies: false,
}],
// Forbid mutable exports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md
'import/no-mutable-exports': 'error',
// Module systems:
// disallow require()
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md
'import/no-commonjs': 'off',
// disallow AMD require/define
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-amd.md
'import/no-amd': 'error',
// No Node.js builtin modules
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md
// TODO: enable?
'import/no-nodejs-modules': 'off',
// Style guide:
// disallow non-import statements appearing before import statements
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/first.md
'import/first': 'error',
// disallow non-import statements appearing before import statements
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/imports-first.md
// deprecated: use `import/first`
'import/imports-first': 'off',
// disallow duplicate imports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
'import/no-duplicates': 'error',
// disallow namespace imports
// TODO: enable?
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
'import/no-namespace': 'off',
// Ensure consistent use of file extension within the import path
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/extensions.md
'import/extensions': ['error', 'ignorePackages', {
js: 'never',
mjs: 'never',
@@ -141,62 +144,62 @@ module.exports = {
}],
// ensure absolute imports are above relative imports and that unassigned imports are ignored
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md
// TODO: enforce a stricter convention in module import order?
'import/order': ['error', { groups: [['builtin', 'external', 'internal']] }],
// Require a newline after the last import/require in a group
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
'import/newline-after-import': 'error',
// Require modules with a single export to use a default export
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md
'import/prefer-default-export': 'error',
// Restrict which files can be imported in a given folder
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md
'import/no-restricted-paths': 'off',
// Forbid modules to have too many dependencies
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md
'import/max-dependencies': ['off', { max: 10 }],
// Forbid import of modules using absolute paths
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md
'import/no-absolute-path': 'error',
// Forbid require() calls with expressions
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md
'import/no-dynamic-require': 'error',
// prevent importing the submodules of other modules
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md
'import/no-internal-modules': ['off', {
allow: [],
}],
// Warn if a module could be mistakenly parsed as a script by a consumer
// leveraging Unambiguous JavaScript Grammar
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/unambiguous.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/unambiguous.md
// this should not be enabled until this proposal has at least been *presented* to TC39.
// At the moment, it's not a thing.
'import/unambiguous': 'off',
// Forbid Webpack loader syntax in imports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md
'import/no-webpack-loader-syntax': 'error',
// Prevent unassigned imports
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md
// importing for side effects is perfectly acceptable, if you need side effects.
'import/no-unassigned-import': 'off',
// Prevent importing the default as if it were named
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-default.md
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-named-default.md
'import/no-named-default': 'error',
// Reports if a module's default export is unnamed
- // https://github.com/benmosher/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md
+ // https://github.com/import-js/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md
'import/no-anonymous-default-export': ['off', {
allowArray: false,
allowArrowFunction: false,
@@ -207,41 +210,74 @@ module.exports = {
}],
// This rule enforces that all exports are declared at the bottom of the file.
- // https://github.com/benmosher/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md
+ // https://github.com/import-js/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md
// TODO: enable?
'import/exports-last': 'off',
// Reports when named exports are not grouped together in a single export declaration
// or when multiple assignments to CommonJS module.exports or exports object are present
// in a single file.
- // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md
+ // https://github.com/import-js/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md
'import/group-exports': 'off',
// forbid default exports. this is a terrible rule, do not use it.
- // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md
+ // https://github.com/import-js/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md
'import/no-default-export': 'off',
+ // Prohibit named exports. this is a terrible rule, do not use it.
+ // https://github.com/import-js/eslint-plugin-import/blob/1ec80fa35fa1819e2d35a70e68fb6a149fb57c5e/docs/rules/no-named-export.md
+ 'import/no-named-export': 'off',
+
// Forbid a module from importing itself
- // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md
+ // https://github.com/import-js/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md
'import/no-self-import': 'error',
// Forbid cyclical dependencies between modules
- // https://github.com/benmosher/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md
- 'import/no-cycle': ['error', { maxDepth: Infinity }],
+ // https://github.com/import-js/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md
+ 'import/no-cycle': ['error', { maxDepth: '∞' }],
// Ensures that there are no useless path segments
- // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/no-useless-path-segments.md
- 'import/no-useless-path-segments': 'error',
+ // https://github.com/import-js/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/no-useless-path-segments.md
+ 'import/no-useless-path-segments': ['error', { commonjs: true }],
// dynamic imports require a leading comment with a webpackChunkName
- // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/dynamic-import-chunkname.md
+ // https://github.com/import-js/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/dynamic-import-chunkname.md
'import/dynamic-import-chunkname': ['off', {
importFunctions: [],
webpackChunknameFormat: '[0-9a-zA-Z-_/.]+',
}],
// Use this rule to prevent imports to folders in relative parent paths.
- // https://github.com/benmosher/eslint-plugin-import/blob/c34f14f67f077acd5a61b3da9c0b0de298d20059/docs/rules/no-relative-parent-imports.md
+ // https://github.com/import-js/eslint-plugin-import/blob/c34f14f67f077acd5a61b3da9c0b0de298d20059/docs/rules/no-relative-parent-imports.md
'import/no-relative-parent-imports': 'off',
+
+ // Reports modules without any exports, or with unused exports
+ // https://github.com/import-js/eslint-plugin-import/blob/f63dd261809de6883b13b6b5b960e6d7f42a7813/docs/rules/no-unused-modules.md
+ // TODO: enable once it supports CJS
+ 'import/no-unused-modules': ['off', {
+ ignoreExports: [],
+ missingExports: true,
+ unusedExports: true,
+ }],
+
+ // Reports the use of import declarations with CommonJS exports in any module except for the main module.
+ // https://github.com/import-js/eslint-plugin-import/blob/1012eb951767279ce3b540a4ec4f29236104bb5b/docs/rules/no-import-module-exports.md
+ 'import/no-import-module-exports': ['error', {
+ exceptions: [],
+ }],
+
+ // Use this rule to prevent importing packages through relative paths.
+ // https://github.com/import-js/eslint-plugin-import/blob/1012eb951767279ce3b540a4ec4f29236104bb5b/docs/rules/no-relative-packages.md
+ 'import/no-relative-packages': 'error',
+
+ // enforce a consistent style for type specifiers (inline or top-level)
+ // https://github.com/import-js/eslint-plugin-import/blob/d5fc8b670dc8e6903dbb7b0894452f60c03089f5/docs/rules/consistent-type-specifier-style.md
+ // TODO, semver-major: enable (just in case)
+ 'import/consistent-type-specifier-style': ['off', 'prefer-inline'],
+
+ // Reports the use of empty named import blocks.
+ // https://github.com/import-js/eslint-plugin-import/blob/d5fc8b670dc8e6903dbb7b0894452f60c03089f5/docs/rules/no-empty-named-blocks.md
+ // TODO, semver-minor: enable
+ 'import/no-empty-named-blocks': 'off',
},
};
diff --git a/packages/eslint-config-airbnb-base/rules/style.js b/packages/eslint-config-airbnb-base/rules/style.js
index d288bc5ad2..2e7f6fed44 100644
--- a/packages/eslint-config-airbnb-base/rules/style.js
+++ b/packages/eslint-config-airbnb-base/rules/style.js
@@ -21,8 +21,7 @@ module.exports = {
'brace-style': ['error', '1tbs', { allowSingleLine: true }],
// require camel case names
- // TODO: semver-major (eslint 5): add ignoreDestructuring: false option
- camelcase: ['error', { properties: 'never' }],
+ camelcase: ['error', { properties: 'never', ignoreDestructuring: false }],
// enforce or disallow capitalization of the first letter of a comment
// https://eslint.org/docs/rules/capitalized-comments
@@ -77,6 +76,9 @@ module.exports = {
// enforce newline at the end of file, with no multiple empty lines
'eol-last': ['error', 'always'],
+ // https://eslint.org/docs/rules/function-call-argument-newline
+ 'function-call-argument-newline': ['error', 'consistent'],
+
// enforce spacing between functions and their invocations
// https://eslint.org/docs/rules/func-call-spacing
'func-call-spacing': ['error', 'never'],
@@ -84,9 +86,9 @@ module.exports = {
// requires function names to match the name of the variable or property to which they are
// assigned
// https://eslint.org/docs/rules/func-name-matching
- // TODO: semver-major (eslint 5): add considerPropertyDescriptor: true
'func-name-matching': ['off', 'always', {
- includeCommonJSModuleExports: false
+ includeCommonJSModuleExports: false,
+ considerPropertyDescriptor: true,
}],
// require function expressions to have a name
@@ -98,13 +100,13 @@ module.exports = {
// TODO: enable
'func-style': ['off', 'expression'],
- // enforce consistent line breaks inside function parentheses
+ // require line breaks inside function parentheses if there are line breaks between parameters
// https://eslint.org/docs/rules/function-paren-newline
- 'function-paren-newline': ['error', 'consistent'],
+ 'function-paren-newline': ['error', 'multiline-arguments'],
- // Blacklist certain identifiers to prevent them being used
- // https://eslint.org/docs/rules/id-blacklist
- 'id-blacklist': 'off',
+ // disallow specified identifiers
+ // https://eslint.org/docs/rules/id-denylist
+ 'id-denylist': 'off',
// this option enforces minimum and maximum identifier lengths
// (variable names, property names etc.)
@@ -140,7 +142,7 @@ module.exports = {
ImportDeclaration: 1,
flatTernaryExpressions: false,
// list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js
- ignoredNodes: ['JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'],
+ ignoredNodes: ['JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXFragment', 'JSXOpeningFragment', 'JSXClosingFragment', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'],
ignoreComments: false
}],
@@ -189,6 +191,13 @@ module.exports = {
after: 'always',
}],
+ // Require or disallow logical assignment logical operator shorthand
+ // https://eslint.org/docs/latest/rules/logical-assignment-operators
+ // TODO, semver-major: enable
+ 'logical-assignment-operators': ['off', 'always', {
+ enforceForIfStatements: true,
+ }],
+
// specify the maximum depth that blocks can be nested
'max-depth': ['off', 4],
@@ -285,7 +294,7 @@ module.exports = {
// disallow un-paren'd mixes of different operators
// https://eslint.org/docs/rules/no-mixed-operators
'no-mixed-operators': ['error', {
- // the list of arthmetic groups disallows mixing `%` and `**`
+ // the list of arithmetic groups disallows mixing `%` and `**`
// with other arithmetic operators.
groups: [
['%', '**'],
@@ -293,14 +302,10 @@ module.exports = {
['%', '-'],
['%', '*'],
['%', '/'],
- ['**', '+'],
- ['**', '-'],
- ['**', '*'],
- ['**', '/'],
- ['&', '|', '^', '~', '<<', '>>', '>>>'],
- ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
+ ['/', '*'],
+ ['&', '|', '<<', '>>', '>>>'],
+ ['==', '!=', '===', '!=='],
['&&', '||'],
- ['in', 'instanceof']
],
allowSamePrecedence: false
}],
@@ -312,8 +317,9 @@ module.exports = {
// https://eslint.org/docs/rules/no-multi-assign
'no-multi-assign': ['error'],
- // disallow multiple empty lines and only one newline at the end
- 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }],
+ // disallow multiple empty lines, only one newline at the end, and no new lines at the beginning
+ // https://eslint.org/docs/rules/no-multiple-empty-lines
+ 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }],
// disallow negated conditions
// https://eslint.org/docs/rules/no-negated-condition
@@ -352,7 +358,8 @@ module.exports = {
],
// disallow space between function identifier and application
- 'no-spaced-func': 'error',
+ // deprecated in favor of func-call-spacing
+ 'no-spaced-func': 'off',
// disallow tab characters entirely
'no-tabs': 'error',
@@ -422,16 +429,25 @@ module.exports = {
'operator-linebreak': ['error', 'before', { overrides: { '=': 'none' } }],
// disallow padding within blocks
- 'padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never' }],
+ 'padded-blocks': ['error', {
+ blocks: 'never',
+ classes: 'never',
+ switches: 'never',
+ }, {
+ allowSingleLineBlocks: true,
+ }],
// Require or disallow padding lines between statements
// https://eslint.org/docs/rules/padding-line-between-statements
'padding-line-between-statements': 'off',
+ // Disallow the use of Math.pow in favor of the ** operator
+ // https://eslint.org/docs/rules/prefer-exponentiation-operator
+ 'prefer-exponentiation-operator': 'error',
+
// Prefer use of an object spread over Object.assign
// https://eslint.org/docs/rules/prefer-object-spread
- // TODO: semver-major (eslint 5): enable
- 'prefer-object-spread': 'off',
+ 'prefer-object-spread': 'error',
// require quotes around object literal property names
// https://eslint.org/docs/rules/quote-props.html
@@ -491,11 +507,11 @@ module.exports = {
'spaced-comment': ['error', 'always', {
line: {
exceptions: ['-', '+'],
- markers: ['=', '!'], // space here to support sprockets directives
+ markers: ['=', '!', '/'], // space here to support sprockets directives, slash for TS /// comments
},
block: {
exceptions: ['-', '+'],
- markers: ['=', '!'], // space here to support sprockets directives
+ markers: ['=', '!', ':', '::'], // space here to support sprockets directives and flow comment types
balanced: true,
}
}],
diff --git a/packages/eslint-config-airbnb-base/rules/variables.js b/packages/eslint-config-airbnb-base/rules/variables.js
index aeab992320..7d61989e6a 100644
--- a/packages/eslint-config-airbnb-base/rules/variables.js
+++ b/packages/eslint-config-airbnb-base/rules/variables.js
@@ -1,4 +1,4 @@
-const restrictedGlobals = require('eslint-restricted-globals');
+const confusingBrowserGlobals = require('confusing-browser-globals');
module.exports = {
rules: {
@@ -16,7 +16,22 @@ module.exports = {
'no-label-var': 'error',
// disallow specific globals
- 'no-restricted-globals': ['error', 'isFinite', 'isNaN'].concat(restrictedGlobals),
+ 'no-restricted-globals': [
+ 'error',
+ {
+ name: 'isFinite',
+ message:
+ 'Use Number.isFinite instead https://github.com/airbnb/javascript#standard-library--isfinite',
+ },
+ {
+ name: 'isNaN',
+ message:
+ 'Use Number.isNaN instead https://github.com/airbnb/javascript#standard-library--isnan',
+ },
+ ].concat(confusingBrowserGlobals.map((g) => ({
+ name: g,
+ message: `Use window.${g} instead. https://github.com/facebook/create-react-app/blob/HEAD/packages/confusing-browser-globals/README.md`,
+ }))),
// disallow declaration of variables already declared in the outer scope
'no-shadow': 'error',
diff --git a/packages/eslint-config-airbnb-base/test/requires.js b/packages/eslint-config-airbnb-base/test/requires.js
index 180a09bf42..8176480fe1 100644
--- a/packages/eslint-config-airbnb-base/test/requires.js
+++ b/packages/eslint-config-airbnb-base/test/requires.js
@@ -1,7 +1,4 @@
-/* eslint
- strict: 0,
- global-require: 0,
- */
+/* eslint strict: 0, global-require: 0 */
'use strict';
diff --git a/packages/eslint-config-airbnb-base/test/test-base.js b/packages/eslint-config-airbnb-base/test/test-base.js
index 07d17b1027..4380bf5567 100644
--- a/packages/eslint-config-airbnb-base/test/test-base.js
+++ b/packages/eslint-config-airbnb-base/test/test-base.js
@@ -6,9 +6,10 @@ import index from '..';
const files = { ...{ index } }; // object spread is to test parsing
-fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => {
+const rulesDir = path.join(__dirname, '../rules');
+fs.readdirSync(rulesDir).forEach((name) => {
// eslint-disable-next-line import/no-dynamic-require
- files[name] = require(`../rules/${name}`); // eslint-disable-line global-require
+ files[name] = require(path.join(rulesDir, name)); // eslint-disable-line global-require
});
Object.keys(files).forEach((
@@ -26,7 +27,7 @@ Object.keys(files).forEach((
// scan rules for react/ and fail if any exist
const reactRuleIds = Object.keys(config.rules)
- .filter(ruleId => ruleId.indexOf('react/') === 0);
+ .filter((ruleId) => ruleId.indexOf('react/') === 0);
t.deepEquals(reactRuleIds, [], 'there are no react/ rules');
});
});
diff --git a/packages/eslint-config-airbnb-base/whitespace-async.js b/packages/eslint-config-airbnb-base/whitespace-async.js
new file mode 100755
index 0000000000..06f4f89075
--- /dev/null
+++ b/packages/eslint-config-airbnb-base/whitespace-async.js
@@ -0,0 +1,49 @@
+#!/usr/bin/env node
+
+const { isArray } = Array;
+const { entries } = Object;
+const { ESLint } = require('eslint');
+
+const baseConfig = require('.');
+const whitespaceRules = require('./whitespaceRules');
+
+const severities = ['off', 'warn', 'error'];
+
+function getSeverity(ruleConfig) {
+ if (isArray(ruleConfig)) {
+ return getSeverity(ruleConfig[0]);
+ }
+ if (typeof ruleConfig === 'number') {
+ return severities[ruleConfig];
+ }
+ return ruleConfig;
+}
+
+async function onlyErrorOnRules(rulesToError, config) {
+ const errorsOnly = { ...config };
+ const cli = new ESLint({
+ useEslintrc: false,
+ baseConfig: config
+ });
+ const baseRules = (await cli.calculateConfigForFile(require.resolve('./'))).rules;
+
+ entries(baseRules).forEach((rule) => {
+ const ruleName = rule[0];
+ const ruleConfig = rule[1];
+ const severity = getSeverity(ruleConfig);
+
+ if (rulesToError.indexOf(ruleName) === -1 && severity === 'error') {
+ if (isArray(ruleConfig)) {
+ errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1));
+ } else if (typeof ruleConfig === 'number') {
+ errorsOnly.rules[ruleName] = 1;
+ } else {
+ errorsOnly.rules[ruleName] = 'warn';
+ }
+ }
+ });
+
+ return errorsOnly;
+}
+
+onlyErrorOnRules(whitespaceRules, baseConfig).then((config) => console.log(JSON.stringify(config)));
diff --git a/packages/eslint-config-airbnb-base/whitespace.js b/packages/eslint-config-airbnb-base/whitespace.js
index d215d4ae6a..01e5198671 100644
--- a/packages/eslint-config-airbnb-base/whitespace.js
+++ b/packages/eslint-config-airbnb-base/whitespace.js
@@ -1,78 +1,61 @@
-const assign = require('object.assign');
-const entries = require('object.entries');
-const CLIEngine = require('eslint').CLIEngine;
+/* eslint global-require: 0 */
-const baseConfig = require('.');
+const { isArray } = Array;
+const { entries } = Object;
+const { CLIEngine } = require('eslint');
-function onlyErrorOnRules(rulesToError, config) {
- const errorsOnly = assign({}, config);
- const cli = new CLIEngine({ baseConfig: config, useEslintrc: false });
- const baseRules = cli.getConfigForFile('./').rules;
+if (CLIEngine) {
+ /* eslint no-inner-declarations: 0 */
+ const whitespaceRules = require('./whitespaceRules');
- entries(baseRules).forEach((rule) => {
- const ruleName = rule[0];
- const ruleConfig = rule[1];
+ const baseConfig = require('.');
- if (rulesToError.indexOf(ruleName) === -1) {
- if (Array.isArray(ruleConfig)) {
- errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1));
- } else if (typeof ruleConfig === 'number') {
- errorsOnly.rules[ruleName] = 1;
- } else {
- errorsOnly.rules[ruleName] = 'warn';
- }
+ const severities = ['off', 'warn', 'error'];
+
+ function getSeverity(ruleConfig) {
+ if (isArray(ruleConfig)) {
+ return getSeverity(ruleConfig[0]);
+ }
+ if (typeof ruleConfig === 'number') {
+ return severities[ruleConfig];
}
- });
+ return ruleConfig;
+ }
- return errorsOnly;
-}
+ function onlyErrorOnRules(rulesToError, config) {
+ const errorsOnly = { ...config };
+ const cli = new CLIEngine({ baseConfig: config, useEslintrc: false });
+ const baseRules = cli.getConfigForFile(require.resolve('./')).rules;
+
+ entries(baseRules).forEach((rule) => {
+ const ruleName = rule[0];
+ const ruleConfig = rule[1];
+ const severity = getSeverity(ruleConfig);
-module.exports = onlyErrorOnRules([
- 'array-bracket-newline',
- 'array-bracket-spacing',
- 'array-element-newline',
- 'arrow-spacing',
- 'block-spacing',
- 'comma-spacing',
- 'computed-property-spacing',
- 'dot-location',
- 'eol-last',
- 'func-call-spacing',
- 'function-paren-newline',
- 'generator-star-spacing',
- 'implicit-arrow-linebreak',
- 'indent',
- 'key-spacing',
- 'keyword-spacing',
- 'line-comment-position',
- 'linebreak-style',
- 'multiline-ternary',
- 'newline-per-chained-call',
- 'no-irregular-whitespace',
- 'no-mixed-spaces-and-tabs',
- 'no-multi-spaces',
- 'no-regex-spaces',
- 'no-spaced-func',
- 'no-trailing-spaces',
- 'no-whitespace-before-property',
- 'nonblock-statement-body-position',
- 'object-curly-newline',
- 'object-curly-spacing',
- 'object-property-newline',
- 'one-var-declaration-per-line',
- 'operator-linebreak',
- 'padded-blocks',
- 'padding-line-between-statements',
- 'rest-spread-spacing',
- 'semi-spacing',
- 'semi-style',
- 'space-before-blocks',
- 'space-before-function-paren',
- 'space-in-parens',
- 'space-infix-ops',
- 'space-unary-ops',
- 'spaced-comment',
- 'switch-colon-spacing',
- 'template-tag-spacing',
- 'import/newline-after-import',
-], baseConfig);
+ if (rulesToError.indexOf(ruleName) === -1 && severity === 'error') {
+ if (isArray(ruleConfig)) {
+ errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1));
+ } else if (typeof ruleConfig === 'number') {
+ errorsOnly.rules[ruleName] = 1;
+ } else {
+ errorsOnly.rules[ruleName] = 'warn';
+ }
+ }
+ });
+
+ return errorsOnly;
+ }
+
+ module.exports = onlyErrorOnRules(whitespaceRules, baseConfig);
+} else {
+ const path = require('path');
+ const { execSync } = require('child_process');
+
+ // NOTE: ESLint adds runtime statistics to the output (so it's no longer JSON) if TIMING is set
+ module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js'), {
+ env: {
+ ...process.env,
+ TIMING: undefined,
+ }
+ })));
+}
diff --git a/packages/eslint-config-airbnb-base/whitespaceRules.js b/packages/eslint-config-airbnb-base/whitespaceRules.js
new file mode 100644
index 0000000000..6b0d3bfec7
--- /dev/null
+++ b/packages/eslint-config-airbnb-base/whitespaceRules.js
@@ -0,0 +1,49 @@
+module.exports = [
+ 'array-bracket-newline',
+ 'array-bracket-spacing',
+ 'array-element-newline',
+ 'arrow-spacing',
+ 'block-spacing',
+ 'comma-spacing',
+ 'computed-property-spacing',
+ 'dot-location',
+ 'eol-last',
+ 'func-call-spacing',
+ 'function-paren-newline',
+ 'generator-star-spacing',
+ 'implicit-arrow-linebreak',
+ 'indent',
+ 'key-spacing',
+ 'keyword-spacing',
+ 'line-comment-position',
+ 'linebreak-style',
+ 'multiline-ternary',
+ 'newline-per-chained-call',
+ 'no-irregular-whitespace',
+ 'no-mixed-spaces-and-tabs',
+ 'no-multi-spaces',
+ 'no-regex-spaces',
+ 'no-spaced-func',
+ 'no-trailing-spaces',
+ 'no-whitespace-before-property',
+ 'nonblock-statement-body-position',
+ 'object-curly-newline',
+ 'object-curly-spacing',
+ 'object-property-newline',
+ 'one-var-declaration-per-line',
+ 'operator-linebreak',
+ 'padded-blocks',
+ 'padding-line-between-statements',
+ 'rest-spread-spacing',
+ 'semi-spacing',
+ 'semi-style',
+ 'space-before-blocks',
+ 'space-before-function-paren',
+ 'space-in-parens',
+ 'space-infix-ops',
+ 'space-unary-ops',
+ 'spaced-comment',
+ 'switch-colon-spacing',
+ 'template-tag-spacing',
+ 'import/newline-after-import'
+];
diff --git a/packages/eslint-config-airbnb/.eslintrc b/packages/eslint-config-airbnb/.eslintrc
index f9bd289286..ab2c306fd9 100644
--- a/packages/eslint-config-airbnb/.eslintrc
+++ b/packages/eslint-config-airbnb/.eslintrc
@@ -4,7 +4,5 @@
// disable requiring trailing commas because it might be nice to revert to
// being JSON at some point, and I don't want to make big changes now.
"comma-dangle": 0,
- // we support node 4
- "prefer-destructuring": 0,
},
}
diff --git a/packages/eslint-config-airbnb/CHANGELOG.md b/packages/eslint-config-airbnb/CHANGELOG.md
index 87bbfc8823..68ba86b925 100644
--- a/packages/eslint-config-airbnb/CHANGELOG.md
+++ b/packages/eslint-config-airbnb/CHANGELOG.md
@@ -1,3 +1,104 @@
+19.0.4 / 2021-12-25
+==================
+ - republish to fix #2529
+
+19.0.3 / 2021-12-24
+==================
+ - [patch] set `namedComponents` option to match style guide
+ - [deps] update `eslint-plugin-react`
+
+19.0.2 / 2021-12-02
+==================
+ - [meta] fix "exports" path (#2525)
+ - [Tests] re-enable tests disabled for the eslint 8 upgrade
+
+19.0.1 / 2021-11-22
+==================
+ - [fix] `whitespace`: update to support eslint 8 (#2517)
+ - [deps] update `eslint-plugin-react`
+ - [dev deps] update `tape`
+
+19.0.0 / 2021-11-10
+==================
+ - [breaking] support `eslint` 8; drop `eslint` < 7
+ - [patch] Explain why `react/jsx-key` is turned off (#2474)
+ - [fix] bump eslint-plugin-react-hooks peer dependency version (#2356)
+ - [patch] Alphabetize the rules for react-a11y.js (#2407)
+ - [Docs] HTTP => HTTPS (#2489)
+ - [readme] clarify hooks requirement (#2482)
+ - [deps] update `eslint-config-airbnb-base`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`, `safe-publish-latest`, `eslint-plugin-import`, `object.entries`
+ - [meta] add `--no-save` to link scripts
+ - [meta] use `prepublishOnly` script for npm 7+
+ - [dev deps] update `@babel/runtime`, `tape`
+
+18.2.1 / 2020-11-06
+==================
+ - [patch] remove deprecated `jsx-a11y/accessible-emoji` rule (#2322)
+ - [patch] Fix ignoreNonDOM typo in jsx-a11y/aria-role rule (#2318)
+ - [patch] Fixed `handle` and `on` ordering in `sort-comp` rule (#2287)
+ - [deps] update `eslint-plugin-jsx-a11y`, `eslint-plugin-react`
+ - [deps] update `eslint-config-airbnb-base`, `object.assign`
+ - [dev deps] update `@babel/runtime`, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`
+
+18.2.0 / 2020-06-18
+==================
+ - [new] add `eslint` `v7` (#2240)
+ - [minor] Allow using `eslint-plugin-react-hooks` v3 and v4 (#2235, #2207)
+ - [minor] Fix typo in no-multiple-empty-lines rule (#2168)
+ - [patch] set `explicitSpread` to ignore for `react/jsx-props-no-spreading` (#2237)
+ - [patch] relax `eslint-plugin-react-hooks` down to v2.3, due to a controversial change in v2.5
+ - [readme] fix typo (#2194)
+ - [deps] update `eslint-config-airbnb-base`, `eslint-plugin-jsx-a11y`, `eslint-plugin-import`, `eslint-plugin-react`, `babel-preset-airbnb`, `eslint-find-rules`, `in-publish`, `tape`, `object.entries`
+ - [tests] fix for eslint 7
+
+18.1.0 / 2020-03-12
+==================
+ - [minor] Support eslint-plugin-react-hooks@2 (#2090)
+ - [minor] add new disabled rules, update eslint
+ - [fix] `whitespace`: only set erroring rules to "warn"
+ - [patch] Remove duplicate `componentDidCatch` (#2108)
+ - [patch] Add `static-variables` to `sort-comp` rule (#2109)
+ - [readme] clarify hooks section in readme (#2074)
+ - [deps] update `eslint`, `eslint-plugin-react`, `eslint-plugin-react-hooks`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `object.entries`
+ - [dev deps] update `@babel/runtime`, `babel-preset-airbnb`, `safe-publish-latest`, `tape`
+ - [tests] re-enable eslint rule `prefer-destructuring` internally (#2110)
+ - [tests] fix eslint errors from c66cfc3 (#2112)
+
+18.0.1 / 2019-08-13
+==================
+ - [patch] `react/state-in-constructor`: fix incorrect configuration
+
+18.0.0 / 2019-08-10
+==================
+ - [breaking] add eslint v6, drop eslint v4
+ - [deps] [breaking] update `eslint-config-airbnb-base`, `eslint-plugin-react`, `eslint-find-rules`, `eslint-plugin-import`
+ - [breaking] Remove rules/strict from 'extends' (#1962)
+ - [breaking] set react version to "detect"
+ - [breaking] disable `label-has-for`; enable `control-has-associated-label`
+ - [breaking] enable `react/jsx-props-no-spreading`
+ - [breaking] enable `react/jsx-fragments`
+ - [minor] enable `react/static-property-placement`
+ - [minor] enable `react/state-in-constructor`
+ - [minor] enable `react/jsx-curly-newline`
+ - [react] Add missing/unsafe lifecycle methods to react/sort-comp rule (#2043)
+ - [react] add componentDidCatch to lifecycle for react/sort-comp (#2060)
+ - [react] add `react-hooks` plugin (#2022)
+ - [dev deps] update babel-related deps to latest
+ - [tests] only run tests in non-lint per-package travis job
+ - [tests] use `eclint` instead of `editorconfig-tools`
+ - [meta] add disabled config for new react and a11y rules
+
+
+17.1.1 / 2019-07-01
+==================
+ - [patch] Turn off `react/no-multi-comp` (#2006)
+ - [patch] extend `no-underscore-dangle` to allow for redux dev tools in the main config instead (#1996)
+ - [meta] add disabled `jsx-fragments` rule
+ - [deps] update `eslint-config-airbnb-base`, `object.entries`, `eslint-plugin-import`, `eslint-plugin-react`, `eslint-plugin-jsx-a11y`, `babel-preset-airbnb`, `tape` (#2005, etc)
+ - [docs] correct JavaScript capitalization (#2046)
+ - [docs] fix docs for whitespace config (#1914, #1871)
+ - [readme] Improve eslint config setup instructions for yarn (#2001)
+
17.1.0 / 2018-08-13
==================
- [new] add eslint v5 support
@@ -366,11 +467,11 @@
[space-in-parens]: https://eslint.org/docs/rules/space-in-parens
[template-curly-spacing]: https://eslint.org/docs/rules/template-curly-spacing
-[react/jsx-space-before-closing]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md
-[react/sort-comp]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md
-[react/display-name]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
-[react/jsx-no-bind]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
-[react/no-is-mounted]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
-[react/prefer-es6-class]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
-[react/jsx-quotes]: https://github.com/yannickcr/eslint-plugin-react/blob/f817e37beddddc84b4788969f07c524fa7f0823b/docs/rules/jsx-quotes.md
-[react/prefer-stateless-function]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
+[react/jsx-space-before-closing]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/jsx-space-before-closing.md
+[react/sort-comp]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/sort-comp.md
+[react/display-name]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/display-name.md
+[react/jsx-no-bind]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/jsx-no-bind.md
+[react/no-is-mounted]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/no-is-mounted.md
+[react/prefer-es6-class]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/prefer-es6-class.md
+[react/jsx-quotes]: https://github.com/jsx-eslint/eslint-plugin-react/blob/f817e37beddddc84b4788969f07c524fa7f0823b/docs/rules/jsx-quotes.md
+[react/prefer-stateless-function]: https://github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/docs/rules/prefer-stateless-function.md
diff --git a/packages/eslint-config-airbnb/README.md b/packages/eslint-config-airbnb/README.md
index f679682936..3b3f43196d 100644
--- a/packages/eslint-config-airbnb/README.md
+++ b/packages/eslint-config-airbnb/README.md
@@ -1,6 +1,6 @@
# eslint-config-airbnb
-[](http://badge.fury.io/js/eslint-config-airbnb)
+[](https://badge.fury.io/js/eslint-config-airbnb)
This package provides Airbnb's .eslintrc as an extensible shared config.
@@ -10,9 +10,9 @@ We export three ESLint configurations for your usage.
### eslint-config-airbnb
-Our default export contains all of our ESLint rules, including ECMAScript 6+ and React. It requires `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, and `eslint-plugin-jsx-a11y`. If you don't need React, see [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base).
+Our default export contains most of our ESLint rules, including ECMAScript 6+ and React. It requires `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, `eslint-plugin-react-hooks`, and `eslint-plugin-jsx-a11y`. Note that it does not enable our React Hooks rules. To enable those, see the [`eslint-config-airbnb/hooks` section](#eslint-config-airbnbhooks).
-If you use yarn, run `npm info "eslint-config-airbnb@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. See below for npm instructions.
+If you don't need React, see [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base).
1. Install the correct versions of each package, which are listed by the command:
@@ -26,6 +26,9 @@ If you use yarn, run `npm info "eslint-config-airbnb@latest" peerDependencies` t
npx install-peerdeps --dev eslint-config-airbnb
```
+ If using **yarn**, you can also use the shortcut described above if you have npm 5+ installed on your machine, as the command will detect that you are using yarn and will act accordingly.
+ Otherwise, run `npm info "eslint-config-airbnb@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency.
+
If using **npm < 5**, Linux/OSX users can run
```sh
@@ -38,7 +41,7 @@ If you use yarn, run `npm info "eslint-config-airbnb@latest" peerDependencies` t
Which produces and runs a command like:
```sh
- npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.#
+ npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# eslint-plugin-react-hooks@^#.#.#
```
If using **npm < 5**, Windows users can either install all the peer dependencies manually, or use the [install-peerdeps](https://github.com/nathanhleung/install-peerdeps) cli tool.
@@ -50,14 +53,18 @@ If you use yarn, run `npm info "eslint-config-airbnb@latest" peerDependencies` t
The cli will produce and run a command like:
```sh
- npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.#
+ npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# eslint-plugin-react-hooks@^#.#.#
```
-2. Add `"extends": "airbnb"` to your .eslintrc
+2. Add `"extends": "airbnb"` to your `.eslintrc`
+
+### eslint-config-airbnb/hooks
+
+This entry point enables the linting rules for React hooks (requires v16.8+). To use, add `"extends": ["airbnb", "airbnb/hooks"]` to your `.eslintrc`.
### eslint-config-airbnb/whitespace
-This entry point only warns on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb/whitespace.js).
+This entry point only errors on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb/whitespace.js).
### eslint-config-airbnb/base
@@ -67,7 +74,7 @@ This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.co
This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base).
-See [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript) and
+See [Airbnb's JavaScript styleguide](https://github.com/airbnb/javascript) and
the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files)
for more information.
diff --git a/packages/eslint-config-airbnb/hooks.js b/packages/eslint-config-airbnb/hooks.js
new file mode 100644
index 0000000000..a7f70284e3
--- /dev/null
+++ b/packages/eslint-config-airbnb/hooks.js
@@ -0,0 +1,6 @@
+module.exports = {
+ extends: [
+ './rules/react-hooks.js',
+ ].map(require.resolve),
+ rules: {}
+};
diff --git a/packages/eslint-config-airbnb/index.js b/packages/eslint-config-airbnb/index.js
index ddd3bfb712..6432e10dda 100644
--- a/packages/eslint-config-airbnb/index.js
+++ b/packages/eslint-config-airbnb/index.js
@@ -1,7 +1,6 @@
module.exports = {
extends: [
'eslint-config-airbnb-base',
- 'eslint-config-airbnb-base/rules/strict',
'./rules/react',
'./rules/react-a11y',
].map(require.resolve),
diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json
index b45487a126..c36359ea7c 100644
--- a/packages/eslint-config-airbnb/package.json
+++ b/packages/eslint-config-airbnb/package.json
@@ -1,19 +1,31 @@
{
"name": "eslint-config-airbnb",
- "version": "17.1.0",
+ "version": "19.0.4",
"description": "Airbnb's ESLint config, following our styleguide",
"main": "index.js",
+ "exports": {
+ ".": "./index.js",
+ "./base": "./base.js",
+ "./hooks": "./hooks.js",
+ "./legacy": "./legacy.js",
+ "./whitespace": "./whitespace.js",
+ "./rules/react": "./rules/react.js",
+ "./rules/react-a11y": "./rules/react-a11y.js",
+ "./rules/react-hooks": "./rules/react-hooks.js",
+ "./package.json": "./package.json"
+ },
"scripts": {
- "prelint": "editorconfig-tools check * rules/* test/*",
+ "prelint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
"lint": "eslint .",
"pretests-only": "node ./test/requires",
"tests-only": "babel-tape-runner ./test/test-*.js",
- "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest",
+ "prepublishOnly": "eslint-find-rules --unused && npm test && safe-publish-latest",
+ "prepublish": "not-in-publish || npm run prepublishOnly",
"pretest": "npm run --silent lint",
"test": "npm run --silent tests-only",
- "link:eslint": "cd node_modules/eslint && npm link && cd -",
- "pretravis": "npm run link:eslint && cd ../eslint-config-airbnb-base && npm link eslint && npm install && npm link && cd - && npm link --no-save eslint-config-airbnb-base",
- "travis": "npm run --silent test",
+ "link:eslint": "cd node_modules/eslint && npm link --production && cd -",
+ "pretravis": "npm run link:eslint && cd ../eslint-config-airbnb-base && npm link --no-save eslint && npm install && npm link && cd - && npm link --no-save eslint-config-airbnb-base",
+ "travis": "npm run --silent tests-only",
"posttravis": "npm unlink --no-save eslint-config-airbnb-base eslint >/dev/null &"
},
"repository": {
@@ -54,31 +66,32 @@
},
"homepage": "https://github.com/airbnb/javascript",
"dependencies": {
- "eslint-config-airbnb-base": "^13.1.0",
- "object.assign": "^4.1.0",
- "object.entries": "^1.0.4"
+ "eslint-config-airbnb-base": "^15.0.0"
},
"devDependencies": {
- "babel-preset-airbnb": "^2.5.3",
- "babel-tape-runner": "^2.0.1",
- "editorconfig-tools": "^0.1.1",
- "eslint": "^4.19.1 || ^5.3.0",
- "eslint-find-rules": "^3.3.1",
- "eslint-plugin-import": "^2.14.0",
- "eslint-plugin-jsx-a11y": "^6.1.1",
- "eslint-plugin-react": "^7.11.0",
- "in-publish": "^2.0.0",
+ "@babel/runtime": "^7.25.6",
+ "babel-preset-airbnb": "^4.5.0",
+ "babel-tape-runner": "^3.0.0",
+ "eclint": "^2.8.1",
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-find-rules": "^4.1.0",
+ "eslint-plugin-import": "^2.30.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.36.1",
+ "eslint-plugin-react-hooks": "^5.1.0",
+ "in-publish": "^2.0.1",
"react": ">= 0.13.0",
- "safe-publish-latest": "^1.1.2",
- "tape": "^4.9.1"
+ "safe-publish-latest": "^2.0.0",
+ "tape": "^5.9.0"
},
"peerDependencies": {
- "eslint": "^4.19.1 || ^5.3.0",
- "eslint-plugin-import": "^2.14.0",
- "eslint-plugin-jsx-a11y": "^6.1.1",
- "eslint-plugin-react": "^7.11.0"
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.30.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.36.1",
+ "eslint-plugin-react-hooks": "^5.1.0"
},
"engines": {
- "node": ">= 4"
+ "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0"
}
}
diff --git a/packages/eslint-config-airbnb/rules/react-a11y.js b/packages/eslint-config-airbnb/rules/react-a11y.js
index dbb073fa67..58065120a4 100644
--- a/packages/eslint-config-airbnb/rules/react-a11y.js
+++ b/packages/eslint-config-airbnb/rules/react-a11y.js
@@ -11,53 +11,115 @@ module.exports = {
},
rules: {
+ // ensure emoji are accessible
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md
+ // disabled; rule is deprecated
+ 'jsx-a11y/accessible-emoji': 'off',
+
+ // Enforce that all elements that require alternative text have meaningful information
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
+ 'jsx-a11y/alt-text': ['error', {
+ elements: ['img', 'object', 'area', 'input[type="image"]'],
+ img: [],
+ object: [],
+ area: [],
+ 'input[type="image"]': [],
+ }],
+
// Enforce that anchors have content
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
'jsx-a11y/anchor-has-content': ['error', { components: [] }],
- // Require ARIA roles to be valid and non-abstract
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
- 'jsx-a11y/aria-role': ['error', { ignoreNonDom: false }],
+ // ensure tags are valid
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md
+ 'jsx-a11y/anchor-is-valid': ['error', {
+ components: ['Link'],
+ specialLink: ['to'],
+ aspects: ['noHref', 'invalidHref', 'preferButton'],
+ }],
+
+ // elements with aria-activedescendant must be tabbable
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md
+ 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
// Enforce all aria-* props are valid.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
'jsx-a11y/aria-props': 'error',
// Enforce ARIA state and property values are valid.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
'jsx-a11y/aria-proptypes': 'error',
+ // Require ARIA roles to be valid and non-abstract
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
+ 'jsx-a11y/aria-role': ['error', { ignoreNonDOM: false }],
+
// Enforce that elements that do not support ARIA roles, states, and
// properties do not have those attributes.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
'jsx-a11y/aria-unsupported-elements': 'error',
- // Enforce that all elements that require alternative text have meaningful information
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
- 'jsx-a11y/alt-text': ['error', {
- elements: ['img', 'object', 'area', 'input[type="image"]'],
- img: [],
- object: [],
- area: [],
- 'input[type="image"]': [],
+ // Ensure the autocomplete attribute is correct and suitable for the form field it is used with
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/29c68596b15c4ff0a40daae6d4a2670e36e37d35/docs/rules/autocomplete-valid.md
+ 'jsx-a11y/autocomplete-valid': ['off', {
+ inputComponents: [],
}],
+ // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
+ 'jsx-a11y/click-events-have-key-events': 'error',
+
+ // Enforce that a control (an interactive element) has a text label.
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md
+ 'jsx-a11y/control-has-associated-label': ['error', {
+ labelAttributes: ['label'],
+ controlComponents: [],
+ ignoreElements: [
+ 'audio',
+ 'canvas',
+ 'embed',
+ 'input',
+ 'textarea',
+ 'tr',
+ 'video',
+ ],
+ ignoreRoles: [
+ 'grid',
+ 'listbox',
+ 'menu',
+ 'menubar',
+ 'radiogroup',
+ 'row',
+ 'tablist',
+ 'toolbar',
+ 'tree',
+ 'treegrid',
+ ],
+ depth: 5,
+ }],
+
+ // ensure tags have content and are not aria-hidden
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
+ 'jsx-a11y/heading-has-content': ['error', { components: [''] }],
+
+ // require HTML elements to have a "lang" prop
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
+ 'jsx-a11y/html-has-lang': 'error',
+
+ // ensure iframe elements have a unique title
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md
+ 'jsx-a11y/iframe-has-title': 'error',
+
// Prevent img alt text from containing redundant words like "image", "picture", or "photo"
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
'jsx-a11y/img-redundant-alt': 'error',
- // require that JSX labels use "htmlFor"
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
- 'jsx-a11y/label-has-for': ['error', {
- components: [],
- required: {
- every: ['nesting', 'id'],
- },
- allowChildren: false,
- }],
+ // Elements with an interactive role and interaction handlers must be focusable
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
+ 'jsx-a11y/interactive-supports-focus': 'error',
// Enforce that a label tag has a text label and an associated control.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md
'jsx-a11y/label-has-associated-control': ['error', {
labelComponents: [],
labelAttributes: [],
@@ -66,77 +128,44 @@ module.exports = {
depth: 25
}],
+ // require HTML element's lang prop to be valid
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md
+ 'jsx-a11y/lang': 'error',
+
+ // media elements must have captions
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md
+ 'jsx-a11y/media-has-caption': ['error', {
+ audio: [],
+ video: [],
+ track: [],
+ }],
+
// require that mouseover/out come with focus/blur, for keyboard-only users
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
'jsx-a11y/mouse-events-have-key-events': 'error',
// Prevent use of `accessKey`
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
'jsx-a11y/no-access-key': 'error',
- // require onBlur instead of onChange
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md
- 'jsx-a11y/no-onchange': 'off',
-
- // Elements with an interactive role and interaction handlers must be focusable
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
- 'jsx-a11y/interactive-supports-focus': 'error',
-
- // Enforce that elements with ARIA roles must have all required attributes
- // for that role.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md
- 'jsx-a11y/role-has-required-aria-props': 'error',
-
- // Enforce that elements with explicit or implicit roles defined contain
- // only aria-* properties supported by that role.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md
- 'jsx-a11y/role-supports-aria-props': 'error',
-
- // Enforce tabIndex value is not greater than zero.
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md
- 'jsx-a11y/tabindex-no-positive': 'error',
-
- // ensure tags have content and are not aria-hidden
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
- 'jsx-a11y/heading-has-content': ['error', { components: [''] }],
-
- // require HTML elements to have a "lang" prop
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
- 'jsx-a11y/html-has-lang': 'error',
-
- // require HTML element's lang prop to be valid
- // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md
- 'jsx-a11y/lang': 'error',
+ // prohibit autoFocus prop
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md
+ 'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }],
// prevent distracting elements, like