diff --git a/CHANGELOG.md b/CHANGELOG.md index 12633effff..555c728d67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,54 @@ +2.1.0 / 2017-05-11 +================== +General refresh pulling in feedback from developers, and various new updates from airbnb standards. + +**General** +- Some minor cleanup of descriptions and code examples. + +**Variables** +- 2.7 Added rule to discourage chaining assignments + +**Objects** +- 3.8 Added new rule to prefer the object spread operator to copy Objects + +**Arrays** +- 4.6 Added new rule to encourage line breaks after open and close array brackets + +**Strings** +- 6.2 Modified rule to encourage long strings on a single line, instead of forbidding them + +**Functions** +- 7.3 Added better caution around when and when not to use default parameters +- 7.11 Modified early exit rule to encourage a single return at the end of the function, unless asserting guard condition + +**Classes** +- 9.5 Added rule to discourage duplicate class member declarations + +**Modules** +- 10.4 Removed rule relating to exporting directly from an import, since it didn't add value + +**Comparison** +- 13.3 Combined two separate rules relating to shortcut syntax into one single rule + +**Whitespace** +- 16.13 Clarified that max line length of 100 characters apply to function code only, not strings + +**Commas** +- 17.2 Revised rule to clarify that trailing commas are not required for single line arrayys/objects + +**Asynchronous Operations** +- 23.2 Added new preferred example using `await` + +**ESlint** +- Updated ruleset to comply with eslint 3.19.0 and babel-eslint 7.2.2 +- Updated deprecated option for `eqeqeq` +- Added ignore options for `no-param-assign` +- Added `no-use-before-define` rule +- Added `no-global-assign` rule +- Added `no-unused-vars` rule +- Modified `max-len` rule to ignore long strings +- Added `rest-spread-spacing` rule + 2.0.1 / 2016-06-09 ================== Published initial version of ESLint ruleset to enforce standards. diff --git a/README.md b/README.md index f9a6dfacbb..4bb56927bd 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ This document is not intended to: ## Types - - [1.1](#types--assign-consistent) The value of a variables should remain the same type as it was originally assigned (a number, string, boolean, array, or object). Avoid reassigning variables to a different type. + - [1.1](#types--assign-consistent) A variable should remain the same type it was originally assigned (a number, string, boolean, array, or object). Avoid reassigning variables to a different type. ```javascript // bad @@ -215,23 +215,19 @@ This document is not intended to: ```javascript // bad - let i, len, dragonball, + let dragonball, items = getItems(), goSportsTeam = true; // bad - let i; const items = getItems(); let dragonball; const goSportsTeam = true; - let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; - let i; - let length; ``` @@ -273,8 +269,8 @@ This document is not intended to: } ``` - - - [2.6](#variables--always-declare) Always declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that. eslint: [`no-undef`](http://eslint.org/docs/rules/no-undef) + + - [2.6](#variables--always-declare) Always use `const` or `let` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that. eslint: [`no-undef`](http://eslint.org/docs/rules/no-undef) ```javascript // bad @@ -284,6 +280,39 @@ This document is not intended to: const superPower = new SuperPower(); ``` + + - [2.7](#variables--no-chain-assignment) Don't chain variable assignments. eslint: [`no-multi-assign`](http://eslint.org/docs/rules/no-multi-assign) + + > Why? Chaining variable assignments creates implicit global variables. + + ```javascript + // bad + (function example() { + // JavaScript interprets this as + // let a = ( b = ( c = 1 ) ); + // The let keyword only applies to variable a; variables b and c become + // global variables. + let a = b = c = 1; + }()); + + console.log(a); // undefined + console.log(b); // 1 + console.log(c); // 1 + + // good + (function example() { + let a = 1; + let b = a; + let c = a; + }()); + + console.log(a); // undefined + console.log(b); // undefined + console.log(c); // undefined + + // the same applies for `const` + ``` + **[⬆ back to top](#table-of-contents)** ## Objects @@ -419,6 +448,26 @@ This document is not intended to: }; ``` + + - [3.8](#objects--rest-spread) Prefer the object spread operator over Object.assign to shallow-copy objects. Use the object rest operator to get a new object with certain properties omitted. + + ```javascript + // very bad + const original = { a: 1, b: 2 }; + const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ + delete copy.a; // so does this + + // bad + const original = { a: 1, b: 2 }; + const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } + + // good + const original = { a: 1, b: 2 }; + const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } + + const { a, ...noA } = copy; // noA => { b: 2, c: 3 } + ``` + **[⬆ back to top](#table-of-contents)** ## Arrays @@ -448,7 +497,7 @@ This document is not intended to: ``` - - [4.3](#arrays--spreads) Use array spreads `...` or the slice() method to make a shallow copy of arrays. Avoid extraneous for loops. + - [4.3](#arrays--spreads) Use array spreads `...` or the slice() method to make a shallow copy of arrays. ```javascript // bad @@ -461,7 +510,7 @@ This document is not intended to: } // good - const itemsCopy = items.slice() + const itemsCopy = items.slice(); // good const itemsCopy = [...items]; @@ -494,6 +543,29 @@ This document is not intended to: [1, 2, 3].map(x => x + 1); ``` + + - [4.6](#arrays--bracket-newline) Use line breaks after open and before close array brackets if an array has multiple lines + + ```javascript + // bad + const objectInArray = [{ + id: 1, + }, { + id: 2, + }]; + + // good + const objectInArray = [ + { + id: 1, + }, + { + id: 2, + }, + ]; + ``` + + **[⬆ back to top](#table-of-contents)** ## Destructuring @@ -579,25 +651,24 @@ This document is not intended to: ``` - - [6.2](#strings--line-length) Strings that cause the line to go over 100 characters should be written across multiple lines using string concatenation. eslint: [`max-len`](http://eslint.org/docs/rules/max-len) + - [6.2](#strings--line-length) Strings that cause the line to go over 100 characters should not be written across multiple lines using string concatenation. - - - [6.3](#strings--concat-perf) Note: If overused, long strings with concatenation could impact performance. [jsPerf](http://jsperf.com/ya-string-concat) & [Discussion](https://github.com/airbnb/javascript/issues/40). + > Why? Broken strings are painful to work with and make code less searchable. ```javascript - // bad - const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; - // bad const errorMessage = 'This is a super long error that was thrown because \ of Batman. When you stop to think about how Batman had anything to do \ with this, you would get nowhere \ fast.'; - // good + // bad const errorMessage = 'This is a super long error that was thrown because ' + - 'of Batman. When you stop to think about how Batman had anything to do ' + - 'with this, you would get nowhere fast.'; + 'of Batman. When you stop to think about how Batman had anything to do ' + + 'with this, you would get nowhere fast.'; + + // good + const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; ``` @@ -631,7 +702,7 @@ This document is not intended to: - [6.5](#strings--eval) Never use `eval()` on a string, it opens too many vulnerabilities. eslint: [`no-eval`](http://eslint.org/docs/rules/no-eval) - - [6.6](#strings--sanitize) Never inject untrusted strings into the DOM unless the has been sanitized. Untrusted strings include anything a user or external source can manipulate, such as query parameters, cookie values, or results from an AJAX call. + - [6.6](#strings--sanitize) Never inject untrusted strings into the DOM unless the value has been sanitized. Untrusted strings include anything a user or external source can manipulate, such as query parameters, cookie values, or results from an AJAX call. **[⬆ back to top](#table-of-contents)** @@ -645,17 +716,12 @@ This document is not intended to: ```javascript // bad foo(obj) { - if (obj.meaningOfLife == null) { - obj.meaningOfLife = 42; - } + obj.key = 1; } // good foo(obj) { - let meaningOfLife = obj.meaningOfLife; - if (meaningOfLife == null) { - meaningOfLife = 42; - } + const key = obj.key != null ? obj.key : 1; } ``` @@ -666,39 +732,39 @@ This document is not intended to: ```javascript // bad - foo(a) { - a = 1; - } - ``` - - - - [7.3](#functions--default-parameters) Use default parameter syntax rather than mutating function parameters. - - ```javascript - // really bad - signup(name) { - // No! We shouldn't mutate function arguments. - // Double bad: if opts is falsy it'll be set to an object which may - // be what you want but it can introduce subtle bugs. + foo(name) { name = name || 'Tony Stark'; } - // still bad - signup (name) { - if (name == null) { - name = 'Tony Stark'; - } + // good + foo(name) { + const localName = name || 'Tony Stark'; } // good + foo(name = 'Tony Stark') { + const localName = name; + } + ``` + + + - [7.3](#functions--default-parameters) When arguments may be omitted completely, use default parameter syntax. + + ```javascript + // bad + // This won't work as expected, the default parameter will + // only be assigned if the value provided is `undefined` signup(name = 'Tony Stark') { // ... } + signup(null); // good - signup({ name = 'Tony Stark' }) { + signup(name = 'Tony Stark') { // ... } + signup(); + ``` @@ -717,13 +783,12 @@ This document is not intended to: - [7.5](#functions--defaults-last) Always put default parameters last. ```javascript - // bad - signup(name = 'Tony Stark', birthdate) { + handleThings(opts = {}, name) { // ... } // good - signup(birthdate, name = 'Tony Stark') { + handleThings(name, opts = {}) { // ... } ``` @@ -812,12 +877,39 @@ This document is not intended to: const add = new Function('a', 'b', 'return a + b'); ``` - - - [7.11](#functions--exit-early) Exit early using return statements at the beginning of the function. This avoids complex if-else blocks and unnecessary indentation. + + - [7.11](#functions--exit-early) Prefer a single return at the end of the function. Avoid adding multiple returns in the middle of a function, since they make the flow harder to debug and encourage inconsistent return types. + + ```javascript + // bad + login(userId) { + if (userId != null) { + return getUser(userId); + } else { + return new User(); + } + }; + + // good + login(userId) { + let user = null; + + if (userId != null) { + user = getUser(userId); + } else { + user = new User(); + } + + return user; + }; + ``` + + + - [7.12](#functions--exit-early) An exception to the above for guard clauses: if asserting whether parameters are valid, exit early using return statements at the beginning of the function. ```javascript add(num1, num2) { - if (num1 == null || num2 == null) { + if (isNaN(num1) || isNaN(num2)) { return false; } @@ -825,8 +917,8 @@ This document is not intended to: }; ``` - - - [7.12](#functions--iife) Add parantheses around immediately invoked function expressions. eslint: [`wrap-iife`](http://eslint.org/docs/rules/wrap-iife) + + - [7.13](#functions--iife) Add parantheses around immediately invoked function expressions. eslint: [`wrap-iife`](http://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. @@ -988,35 +1080,21 @@ This document is not intended to: } } ``` + + + + - [9.5](#classes--no-duplicate-members) Avoid duplicate class members. eslint: [`no-dupe-class-members`] (http://eslint.org/docs/rules/no-dupe-class-members) - - - [9.5](#classes--no-useless) Classes have a default constructor if one is not specified. An empty constructor function or one that just delegates to a parent class is unnecessary. [`no-useless-constructor`](http://eslint.org/docs/rules/no-useless-constructor) + > Why? Duplicate class member declarations will silently prefer the last one - having duplicates is almost certainly a bug. ```javascript // bad - class Jedi { - constructor() {} - - getName() { - return this.name; - } - } - - // bad - class Rey extends Jedi { - constructor(...args) { - super(...args); - } - } - - // good - class Rey extends Jedi { - constructor(...args) { - super(...args); - this.name = 'Rey'; - } + class Foo { + bar() { return 1; } + bar() { return 2; } } ``` + **[⬆ back to top](#table-of-contents)** @@ -1039,33 +1117,28 @@ This document is not intended to: import NerderyStyleGuide from './NerderyStyleGuide'; ``` - - - [10.3](#modules--no-wildcard) Do not use wildcard imports. - - > Why? This makes sure you have a single default export. + + - [10.3](#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) ```javascript // bad - import * as NerderyStyleGuide from './NerderyStyleGuide'; + export function foo() {} // good - import NerderyStyleGuide from './NerderyStyleGuide'; + export default function foo() {} ``` - - - [10.4](#modules--no-export-from-import) And do not export directly from an import. + + - [10.4](#modules--no-wildcard) Do not use wildcard imports. - > Why? Although the one-liner is concise, having one clear way to import and one clear way to export makes things consistent. + > Why? This makes sure you have a single default export. ```javascript // bad - // filename es6.js - export { es6 as default } from './NerderyStyleGuide'; + import * as NerderyStyleGuide from './NerderyStyleGuide'; // good - // filename es6.js - import { es6 } from './NerderyStyleGuide'; - export default es6; + import NerderyStyleGuide from './NerderyStyleGuide'; ``` @@ -1086,7 +1159,9 @@ This document is not intended to: ## Iterators and Generators - - [11.1](#iterators--nope) Avoid using iterators and `for-of` loops. Prefer JavaScript's higher-order functions like `map()` and `reduce()`. + - [11.1](#iterators--nope) Avoid using iterators and `for-of` loops. Prefer JavaScript's higher-order functions instead of loops like `for-in` or `for-of`. + + > Use `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / ... to iterate over arrays, and `Object.keys()` / `Object.values()` / `Object.entries()` to produce arrays so you can iterate over objects. ```javascript const numbers = [1, 2, 3, 4, 5]; @@ -1094,19 +1169,28 @@ This document is not intended to: // bad let sum = 0; for (let num of numbers) { - sum += num; + sum += num; } - sum === 15; - // good let sum = 0; numbers.forEach(num => sum += num); - sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); - sum === 15; + + // bad + const increasedByOne = []; + for (let i = 0; i < numbers.length; i++) { + increasedByOne.push(numbers[i] + 1); + } + + // good + const increasedByOne = []; + numbers.forEach(num => increasedByOne.push(num + 1)); + + // best (keeping it functional) + const increasedByOne = numbers.map(num => num + 1); ``` @@ -1184,36 +1268,44 @@ This document is not intended to: ``` - - [13.3](#comparison--no-shortcuts) Avoid the "shortcut" syntax that omits the comparison operator in most cases. + - [13.3](#comparison--no-shortcuts) Use shortcuts for booleans, but explicit comparisons for strings and numbers. - > Why? JavaScript will try to coerce the expression into a boolean value, which could lead to unintended results. Be more descriptive about what you want to compare. + > Why? JavaScript will try to coerce strings and numbers into a boolean value, which could lead to unintended results. Be more descriptive about what you want to compare. For more information see [Truth Equality and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll. ```javascript // bad - if (name) { + if (isValid === true) { // ... } // good - if (name != null) { + if (isValid) { // ... } - ``` - - - [13.4](#comparison--shortcuts-boolean) Do use the shortcut syntax if comparing a boolean true/false value. + // bad + if (name) { + // ... + } - ```javascript // good - let isValid = true; + if (name !== '') { + // ... + } - if (isValid) { + // bad + if (collection.length) { + // ... + } + + // good + if (collection.length > 0) { // ... } ``` - - - [13.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`](http://eslint.org/docs/rules/no-case-declarations). + + - [13.4](#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`](http://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. @@ -1246,8 +1338,8 @@ This document is not intended to: } ``` - - - [13.6](#comparison--nested-ternaries) Ternaries should not be nested and should generally be single line expressions. eslint: [`no-nested-ternary`](http://eslint.org/docs/rules/no-nested-ternary). + + - [13.5](#comparison--nested-ternaries) Ternaries should not be nested and should be single line expressions. eslint: [`no-nested-ternary`](http://eslint.org/docs/rules/no-nested-ternary). ```javascript // bad @@ -1304,7 +1396,7 @@ This document is not intended to: ## Comments - - [15.1](#comments--multiline) Use `/** ... */` for multi-line comments. Include a description, specify types and values for all parameters and return values. eslint: [`valid-jsdoc`](http://eslint.org/docs/rules/valid-jsdoc) + - [15.1](#comments--multiline) Use `/** ... */` for multi-line comments. Include types for all parameters and return values. eslint: [`valid-jsdoc`](http://eslint.org/docs/rules/valid-jsdoc) ```javascript // bad @@ -1452,6 +1544,7 @@ This document is not intended to: age: '1 year', breed: 'Bernese Mountain Dog', }); + ``` @@ -1661,9 +1754,42 @@ This document is not intended to: // good const foo = { clark: 'kent' }; ``` + + + - [16.12](#whitespace--signature-invocation-indentation) Functions with multiline signatures, or invocations, should be indented with each item on a line by itself, with a trailing comma on the last item. + + ```javascript + // bad + function foo(bar, + baz, + quux) { + // ... + } + + // good + function foo( + bar, + baz, + quux, + ) { + // ... + } + + // bad + console.log(foo, + bar, + baz); + + // good + console.log( + foo, + bar, + baz, + ); + ``` - - - [16.12](#whitespace--max-len) Avoid having lines of code that are longer than 100 characters (including whitespace). eslint: [`max-len`](http://eslint.org/docs/rules/max-len) + + - [16.13](#whitespace--max-len) Avoid having lines of code that are longer than 100 characters (including whitespace). eslint: [`max-len`](http://eslint.org/docs/rules/max-len) > Why? This ensures readability and maintainability. @@ -1689,85 +1815,64 @@ This document is not intended to: ## Commas - - - [17.1](#commas--leading-trailing) Leading commas: **Nope.** eslint: [`comma-style`](http://eslint.org/docs/rules/comma-style) + + - [17.1](#commas--multiline) Use trailing commas for multi-line arrays and objects. eslint: [`comma-style`](http://eslint.org/docs/rules/comma-style) [`comma-dangle`](http://eslint.org/docs/rules/comma-dangle) + + > Why? This leads to cleaner git diffs. ```javascript // bad - const story = [ - once - , upon - , aTime + const heroes = [ + 'Batman' + , 'Superman' + ]; + + // bad + const heroes = [ + 'Batman', + 'Superman' ]; // good - const story = [ - once, - upon, - aTime, + const heroes = [ + 'Batman', + 'Superman', ]; // bad const hero = { firstName: 'Ada' , lastName: 'Lovelace' - , birthYear: 1815 - , superPower: 'computers' }; - // good + // bad const hero = { firstName: 'Ada', - lastName: 'Lovelace', - birthYear: 1815, - superPower: 'computers', - }; - ``` - - - - [17.2](#commas--dangling) Additional trailing comma: **Yup.** eslint: [`comma-dangle`](http://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](es5/README.md#commas) in legacy browsers. - - ```javascript - // bad - git diff without trailing comma - const hero = { - firstName: 'Florence', - - lastName: 'Nightingale' - + lastName: 'Nightingale', - + inventorOf: ['coxcomb graph', 'modern nursing'] + lastName: 'Lovelace' }; - // good - git diff with trailing comma + // good const hero = { - firstName: 'Florence', - lastName: 'Nightingale', - + inventorOf: ['coxcomb chart', 'modern nursing'], + firstName: 'Ada', + lastName: 'Lovelace', }; + ``` - // bad - const hero = { - firstName: 'Dana', - lastName: 'Scully' - }; + + - [17.2](#commas--singleline) No trailing commas for single-line arrays and objects. eslint: [`comma-dangle`](http://eslint.org/docs/rules/comma-dangle) + ```javascript // bad - const heroes = [ - 'Batman', - 'Superman' - ]; + const heroes = ['Batman', 'Superman',]; // good - const hero = { - firstName: 'Dana', - lastName: 'Scully', - }; + const heroes = ['Batman', 'Superman']; + + // bad + const hero = { firstName: 'Ada', lastName: 'Lovelace', }; // good - const heroes = [ - 'Batman', - 'Superman', - ]; + const hero = { firstName: 'Ada', lastName: 'Lovelace' }; ``` **[⬆ back to top](#table-of-contents)** @@ -1796,27 +1901,29 @@ This document is not intended to: ```javascript // bad - class Wizard { - perform = 'Smoke Rings'; + class Plane { + flew = 0; + powering = 4; - impressiveMagicalStuff() { + airborne() { // ... } - scared() { + grounded() { // ... } } // good - class Wizard { - ability = 'Smoke Rings'; + class Plane { + altitude = 0; + engineCount = 4; - useMagic() { + takeoff() { // ... } - runAway() { + land() { // ... } } @@ -1920,7 +2027,7 @@ This document is not intended to: ``` - - [19.7](#naming--self-this) Don't save references to `this`. Use arrow functions or Function#bind. + - [19.7](#naming--self-this) Don't save references to `this`. Use arrow functions or [Function#bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). ```javascript // bad @@ -1968,39 +2075,23 @@ This document is not intended to: import CheckBox from './CheckBox'; ``` - - - [19.9](#naming--camelCase-default-export) Use camelCase when you export-default a function. Your filename should be identical to your function's name. - - ```javascript - function makeStyleGuide() { - } - - export default makeStyleGuide; - ``` - - - - [19.10](#naming--PascalCase-singleton) Use PascalCase when you export a singleton / function library / bare object. - - ```javascript - const NerderyStyleGuide = { - es6: { - } - }; - - export default NerderyStyleGuide; - ``` - - - - [19.11](#naming--constants) Constant values should be in all capitals and underscore-separated. + + - [19.9](#naming--constants) Constant values should be in all capitals and underscore-separated. ```javascript const MAXIMUM_POWER = 9000; ``` - - - [19.12](#naming--constants-grouping) Group related constants in an object. All properties should be named using the same convention for constants. + + - [19.10](#naming--constants-grouping) Group related constants in an object. All properties should be named using the same convention for constants. ```javascript + // bad + const SELECTOR_ACTIVE = '.isActive'; + const SELECTOR_DISABLED = '.isDisabled'; + const SELECTOR_MODAL_CLOSE = '.js-modal-close'; + + // good const SELECTORS = { ACTIVE: '.isActive', DISABLED: '.isDisabled', @@ -2008,8 +2099,8 @@ This document is not intended to: }; ``` - - - [19.13](#naming--symbols) If the values you set for constants are arbitrary and don't add meaning, use Symbol() instead. + + - [19.11](#naming--symbols) If the values you set for constants are arbitrary and don't add meaning, use Symbol() instead. ```javascript // bad @@ -2056,7 +2147,6 @@ This document is not intended to: prefer: ```javascript - //good class Dragon { _age = 0; @@ -2199,7 +2289,8 @@ This document is not intended to: waitFor(milliseconds) { return new Promise((resolve, reject) => { window.setTimeout( - () => { resolve(); }, milliseconds + () => { resolve(); }, + milliseconds ); }); } @@ -2209,10 +2300,10 @@ This document is not intended to: ``` - - [23.2](#asynchronous--nested-promises) Avoid nesting promises several layers deep. Instead, compose a sequence of promises using a flat chain. + - [23.2](#asynchronous--nested-promises) Avoid nesting promises several layers deep. Instead, compose a sequence of promises using a flat chain. Better yet, use the await syntax. ```javascript - //bad + // bad waitFor(1000) .then(() => { waitFor(2000) @@ -2224,7 +2315,7 @@ This document is not intended to: }) }); - //good + // good waitFor(1000) .then(() => { return waitFor(2000); @@ -2235,6 +2326,14 @@ This document is not intended to: .then(() => { console.log('Done waiting!'); }); + + // best + async function mySequence() { + await waitFor(1000); + await waitFor(2000); + await waitFor(3000); + console.log('Done waiting!'); + } ``` @@ -2246,6 +2345,7 @@ This document is not intended to: waitFor(1000) .then(() => { console.log('Done waiting!'); }) .catch(exception => { console.error('Error in waitFor():', exception); }); + ``` **[⬆ back to top](#table-of-contents)** diff --git a/linters/.eslintrc b/linters/.eslintrc index f3f8c384b0..9311fb04c4 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -1,14 +1,15 @@ ################################################################################################### # ESLint rules enforcing Nerdery JavaScript standards -# https://github.com/thenerdery/javascript-standards/linters +# https://github.com/thenerdery/javascript-standards/tree/master/linters # -# Last tested with eslint v2.8.0 and babel-eslint v6.0.0 +# Last tested with eslint v3.19.0 and babel-eslint v7.2.2 ################################################################################################### { "env": { "browser": true, - "node": false + "node": false, + "es6": true }, "globals": { "module": true, @@ -86,7 +87,7 @@ # COMPARISON ############################################################################################### - "eqeqeq": [2, "allow-null"], # Require === and !==, allow null check + "eqeqeq": [2, "always", { null: "ignore" }], # Require === and !==, allow null check "no-case-declarations": 2, # Require case statements are wrapped in parens "no-undefined": 2, # Disallow use of undefined variable "no-nested-ternary": 2, # Disallow nested ternaries @@ -101,7 +102,7 @@ # FUNCTIONS ############################################################################################### - "no-param-reassign": [2, {"props": true}], # Disallow reassignment of parameters + "no-param-reassign": [2, {"props": false }], # Disallow reassignment of parameters "max-params": [2, 5], # Disallow more than 5 parameters "prefer-rest-params": 2, # Require rest parameters instead of `arguments` "wrap-iife": [2, "outside"], # Require IIFEs to be wrapped @@ -159,7 +160,7 @@ "no-eval": 2, # Disallow eval() ############################################################################################### - #TYPES + # TYPES ############################################################################################### "no-implicit-coercion": 2, # Disallow type conversion with shorter notations @@ -176,6 +177,14 @@ "no-var": 2, # Disallow use of `var` "one-var": [2, "never"], # Disallow one variable declaration per scope "no-undef": 2, # Disallow undeclared variables + "no-use-before-define": 2, # Disallow using variables before declaration + "no-global-assign": 2, # Disallow overwriting native variables + "no-multi-assign": 2, # Disallow multiple assignments on one line + "no-unused-vars": [2, { # Disallow unused variables + "vars": "local", + "args": "after-used", + "ignoreRestSiblings": true + }], ############################################################################################### # WHITESPACE @@ -193,7 +202,11 @@ "object-curly-spacing": [2, "always"], # Require spaces inside object curly braces "max-len": [2, { # Disallow lines over 100 characters "code": 100, - "ignoreUrls": true + "ignoreUrls": true, + "ignoreComments": false, + "ignoreRegExpLiterals": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true }], "keyword-spacing": [2, { # Require spacing before and after keywords "before": true, @@ -203,6 +216,7 @@ "padded-blocks": [2, "never"], # Require padding within blocks "no-mixed-spaces-and-tabs": 2, # Disallow mixing of spaces and tabs "no-trailing-spaces": 2, # Disallow trailing spaces - "eol-last": 2 # Require file to end with a newline + "eol-last": 2, # Require file to end with a newline + "rest-spread-spacing": 2 # Disallow spaces between spread operator } } diff --git a/linters/Gruntfile.js b/linters/Gruntfile.js index c94cf69373..9c84260199 100644 --- a/linters/Gruntfile.js +++ b/linters/Gruntfile.js @@ -6,10 +6,7 @@ module.exports = function(grunt) { grunt.initConfig({ eslint: { - target: ['tests/**/*.js'], - options: { - format: 'table', - }, + target: ['tests/**/*.js'] }, }); diff --git a/linters/README.md b/linters/README.md index 4448ed5bd3..7fc2d7cf80 100644 --- a/linters/README.md +++ b/linters/README.md @@ -9,15 +9,15 @@ https://github.com/thenerdery/javascript-standards/linters 1. Add the following lines to your project's package.json: "devDependencies": { - "babel-eslint": "6.0.4", - "eslint": "2.10.2", + "babel-eslint": "7.2.2", + "eslint": "3.19.0", } 1. Install the package npm install -1. If eslint is installed globally, we recommend uninstalling it +1. If eslint is installed globally, please uninstall it. The globally installed version might conflict with the specific version needed by your project. npm uninstall -g eslint @@ -42,9 +42,12 @@ Sublime Text 2 not supported. ### WebStorm -1. Navigate to `Languages and Frameworks > JavaScript > Code Quality Tools > ESLint` -1. Check `Enable` and the `.eslintrc` file will be used. -1. For more info: [https://www.jetbrains.com/help/webstorm/2016.1/eslint.html](https://www.jetbrains.com/help/webstorm/2016.1/eslint.html) +1. Navigate to `Preferences -> Languages and Frameworks > JavaScript > Code Quality Tools > ESLint` +1. Check `Enable` +1. Specify Node Interpreter as the path where you've installed node.js. If you've used the `n` version manager to install node, this will be located under /yourusername/.node/bin/node +1. Specify ESLint Package as the path where you've installed ESLint. This may already be pre-selected with the correct path; if not, navigate to /{your project folder}/node_modules/eslint + +For more info: [https://www.jetbrains.com/help/webstorm/2016.1/eslint.html](https://www.jetbrains.com/help/webstorm/2016.1/eslint.html) ## Testing diff --git a/linters/package.json b/linters/package.json index 619b04f5b3..4e9de8d16b 100644 --- a/linters/package.json +++ b/linters/package.json @@ -1,7 +1,7 @@ { "name": "nerdery-eslint", "description": "Nerdery ESLint Ruleset", - "version": "1.0.0", + "version": "2.1.0", "repository": { "type": "git", "url": "https://github.com/thenerdery/javascript-standards.git" @@ -11,7 +11,9 @@ "lint", "nerdery", "es6", - "es2015" + "es7", + "es2015", + "es2016" ], "author": "Nerdery", "license": "MIT", @@ -20,11 +22,11 @@ }, "homepage": "https://github.com/thenerdery/javascript-standards", "dependencies": { - "eslint": "2.8.0", - "babel-eslint": "6.0.0", + "eslint": "3.19.0", + "babel-eslint": "7.2.2", "grunt": "1.0.1", - "grunt-eslint": "18.1.0", - "jit-grunt": "0.9.1", - "load-grunt-tasks": "3.1.0" + "grunt-eslint": "19.0.0", + "jit-grunt": "0.10.0", + "load-grunt-tasks": "3.5.2" } } diff --git a/linters/tests/accessors.js b/linters/tests/accessors.js index b33f0074e6..d041b16858 100644 --- a/linters/tests/accessors.js +++ b/linters/tests/accessors.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#accessors--use-them -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad class Dragon { @@ -39,7 +41,7 @@ }()); // https://github.com/thenerdery/javascript-standards#accessors--use-them -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // good class Dragon { diff --git a/linters/tests/arrays.js b/linters/tests/arrays.js index 49cc75c09f..6ada171ca6 100644 --- a/linters/tests/arrays.js +++ b/linters/tests/arrays.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#arrays--literals // eslint: no-array-constructor (function() { @@ -11,7 +13,7 @@ }()); // https://github.com/thenerdery/javascript-standards#arrays--push -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad const someStack = []; @@ -25,7 +27,7 @@ }()); // https://github.com/thenerdery/javascript-standards#arrays--spreads -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad const items = [1, 2, 3]; @@ -51,7 +53,7 @@ }()); // https://github.com/thenerdery/javascript-standards#arrays--from -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo); @@ -91,3 +93,24 @@ const args = [1, 2, 3, 4]; Math.max(...args); }()); + +// https://github.com/thenerdery/javascript-standards#arrays--bracket-newline +// eslint: array-bracket-newline +(function() { + // bad + const objectInArray = [{ + id: 1, + }, { + id: 2, + }]; + + // good + const objectInArray = [ + { + id: 1, + }, + { + id: 2, + }, + ]; +}()); diff --git a/linters/tests/arrow-functions.js b/linters/tests/arrow-functions.js index 3d6b85b466..ecddc46fd0 100644 --- a/linters/tests/arrow-functions.js +++ b/linters/tests/arrow-functions.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#arrows--use-them // eslint: prefer-arrow-callback (function() { diff --git a/linters/tests/asynchronous-operations.js b/linters/tests/asynchronous-operations.js index 0dd8ee2581..81d23e017b 100644 --- a/linters/tests/asynchronous-operations.js +++ b/linters/tests/asynchronous-operations.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#asynchronous--nested-promises -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const Promise = null; function waitFor(milliseconds) { @@ -47,7 +49,7 @@ }()); // https://github.com/thenerdery/javascript-standards#asynchronous--catch -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const Promise = null; function waitFor(milliseconds) { diff --git a/linters/tests/blocks.js b/linters/tests/blocks.js index 948f636565..b1aeabdc78 100644 --- a/linters/tests/blocks.js +++ b/linters/tests/blocks.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#blocks--braces // eslint: curly (function() { diff --git a/linters/tests/classes.js b/linters/tests/classes.js index 03b04410cc..4ab8ec6cd9 100644 --- a/linters/tests/classes.js +++ b/linters/tests/classes.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#classes--use-them -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function Queue(contents = []) { @@ -33,7 +35,7 @@ }()); // https://github.com/thenerdery/javascript-standards#classes--static -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad class Queue { @@ -65,7 +67,7 @@ }()); // https://github.com/thenerdery/javascript-standards#classes--extends -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad class Queue { @@ -95,7 +97,7 @@ }()); // https://github.com/thenerdery/javascript-standards#classes--tostring -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // good class Jedi { @@ -113,43 +115,6 @@ } }()); - -// https://github.com/thenerdery/javascript-standards#classes--no-useless -// estlint: no-useless-constructor -(function() { - // bad - class Jedi { - constructor() {} - - getName() { - return this.name; - } - } -}()); - -(function() { - // bad - class Jedi {} - - class Rey extends Jedi { - constructor(...args) { - super(...args); - } - } -}()); - -(function() { - // good - class Jedi {} - - class Rey extends Jedi { - constructor(...args) { - super(...args); - this.name = 'Rey'; - } - } -}()); - // https://github.com/thenerdery/javascript-standards#classes // eslint: no-dupe-class-members (function() { diff --git a/linters/tests/commas.js b/linters/tests/commas.js index cc60f16577..0ba7e4c1eb 100644 --- a/linters/tests/commas.js +++ b/linters/tests/commas.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#commas--leading-trailing // eslint: comma-style (function() { diff --git a/linters/tests/comments.js b/linters/tests/comments.js index 21b200e11b..478a646001 100644 --- a/linters/tests/comments.js +++ b/linters/tests/comments.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#comments--multiline // eslint: valid-jsdoc (function() { @@ -46,7 +48,7 @@ }()); // https://github.com/thenerdery/javascript-standards#comments--singleline -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad const active = true; // is current tab diff --git a/linters/tests/comparison.js b/linters/tests/comparison.js index 0ae1a9b823..df74f350b1 100644 --- a/linters/tests/comparison.js +++ b/linters/tests/comparison.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#comparison--eqeqeq // eslint: eqeqeq (function() { @@ -39,7 +41,7 @@ }()); // https://github.com/thenerdery/javascript-standards#comparison--no-shortcuts -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad const name = null; @@ -59,7 +61,7 @@ }()); // https://github.com/thenerdery/javascript-standards#comparison--shortcuts-boolean -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // good const isValid = true; diff --git a/linters/tests/destructuring.js b/linters/tests/destructuring.js index e45b7db5d6..06fe88a385 100644 --- a/linters/tests/destructuring.js +++ b/linters/tests/destructuring.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#destructuring--object -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function getFullName(user) { @@ -26,7 +28,7 @@ }()); // https://github.com/thenerdery/javascript-standards#destructuring--array -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const arr = [1, 2, 3, 4]; @@ -43,7 +45,7 @@ }()); // https://github.com/thenerdery/javascript-standards#destructuring--object-over-array -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function processInput(input) { diff --git a/linters/tests/dom-interaction.js b/linters/tests/dom-interaction.js index 5ab388248f..85ab0e4af2 100644 --- a/linters/tests/dom-interaction.js +++ b/linters/tests/dom-interaction.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#dom--dollar-prefix -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const $ = null; // bad diff --git a/linters/tests/functions.js b/linters/tests/functions.js index d1ab3f9be3..b945f9539a 100644 --- a/linters/tests/functions.js +++ b/linters/tests/functions.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#functions--mutate-parameters // eslint: no-param-reassign (function() { @@ -23,7 +25,7 @@ // eslint: no-param-reassign (function() { // bad - function foo(a) { + function foo(e) { a = 1; } }()); @@ -61,7 +63,7 @@ }()); // https://github.com/thenerdery/javascript-standards#functions--default-side-effects -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad let b = 0; @@ -72,7 +74,7 @@ }()); // https://github.com/thenerdery/javascript-standards#functions--defaults-last -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function signup(name = 'Tony Stark', birthdate) { @@ -161,7 +163,7 @@ }()); // https://github.com/thenerdery/javascript-standards#functions--exit-early -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // good function add(num1, num2) { diff --git a/linters/tests/iterators-and-generators.js b/linters/tests/iterators-and-generators.js index d016aa5603..2a85da0c8c 100644 --- a/linters/tests/iterators-and-generators.js +++ b/linters/tests/iterators-and-generators.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#iterators--nope -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad const numbers = [1, 2, 3, 4, 5]; diff --git a/linters/tests/modules.js b/linters/tests/modules.js index 9562449b7c..6671429fff 100644 --- a/linters/tests/modules.js +++ b/linters/tests/modules.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#modules--use-them -// eslint: ??? +// eslint: (no known rule enforcing this exists) // bad const NerderyStyleGuide0 = require('./NerderyStyleGuide'); diff --git a/linters/tests/naming-conventions.js b/linters/tests/naming-conventions.js index 20dcdd2d51..4330c48d1c 100644 --- a/linters/tests/naming-conventions.js +++ b/linters/tests/naming-conventions.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#naming--camelCase // eslint: camelcase (function() { @@ -40,7 +42,7 @@ }()); // https://github.com/thenerdery/javascript-standards#naming--leading-underscore -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function test() { @@ -57,7 +59,7 @@ }()); // https://github.com/thenerdery/javascript-standards#naming--self-this -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function foo() { diff --git a/linters/tests/objects.js b/linters/tests/objects.js index 57fe7327fc..3ae0dbc5b0 100644 --- a/linters/tests/objects.js +++ b/linters/tests/objects.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#objects--no-new // eslint: no-new-object (function() { @@ -34,7 +36,7 @@ }()); // https://github.com/thenerdery/javascript-standards#objects--computed-properties -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { function getKey(k) { return `a key named ${k}`; @@ -102,7 +104,7 @@ }()); // https://github.com/thenerdery/javascript-standards#objects--grouped-shorthand -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { function makePoint(x, y) { return { diff --git a/linters/tests/properties.js b/linters/tests/properties.js index 0541912d54..a11b9630b9 100644 --- a/linters/tests/properties.js +++ b/linters/tests/properties.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#properties--dot // eslint: dot-notation (function() { @@ -21,7 +23,7 @@ }()); // https://github.com/thenerdery/javascript-standards#properties--bracket -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const luke = { jedi: true, diff --git a/linters/tests/semicolons.js b/linters/tests/semicolons.js index 5df4306197..346c010a31 100644 --- a/linters/tests/semicolons.js +++ b/linters/tests/semicolons.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#semicolons--required // eslint: semi (function() { diff --git a/linters/tests/strings.js b/linters/tests/strings.js index e0d266fd70..2ec1e0ade6 100644 --- a/linters/tests/strings.js +++ b/linters/tests/strings.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#strings--quotes // eslint: quotes (function() { diff --git a/linters/tests/types.js b/linters/tests/types.js index 268aee91c3..86a90cbd82 100644 --- a/linters/tests/types.js +++ b/linters/tests/types.js @@ -1,5 +1,7 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#types--assign-consistent -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad let count = 1; @@ -13,7 +15,7 @@ }()); // https://github.com/thenerdery/javascript-standards#types--return-consistent -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { // bad function pressYourLuck(bigMoney) { @@ -26,7 +28,7 @@ }()); // https://github.com/thenerdery/javascript-standards#types--coercion-strings -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { function test() { this.reviewScore = 9; @@ -124,7 +126,7 @@ }()); // https://github.com/thenerdery/javascript-standards#types--comment-deviations -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const inputValue = '4'; @@ -137,7 +139,7 @@ }()); // https://github.com/thenerdery/javascript-standards#types--exceptions -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { function divide(numerator, denominator) { if (denominator === 0) { diff --git a/linters/tests/variables.js b/linters/tests/variables.js index c815ef863a..84e72f3cd7 100644 --- a/linters/tests/variables.js +++ b/linters/tests/variables.js @@ -54,7 +54,7 @@ }()); // https://github.com/thenerdery/javascript-standards#variables--const-let-group -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const getItems = () => {}; @@ -87,7 +87,7 @@ }()); // https://github.com/thenerdery/javascript-standards#variables--define-where-used -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const getName = () => {}; // bad - unnecessary function call @@ -141,3 +141,51 @@ // good const superPower = new SuperPower(); }()); + +// eslint: no-use-before-define +(function() { + // bad + alert(foo); + const foo = 1; +}()); + +// eslint: no-global-assign +(function() { + window = {}; +}()); + +// https://github.com/thenerdery/javascript-standards#variables--no-chain-assignment +// eslint: no-multi-assign +(function() { + // bad + (function example() { + // JavaScript interprets this as + // let a = ( b = ( c = 1 ) ); + // The let keyword only applies to variable a; variables b and c become + // global variables. + let a = b = c = 1; + }()); + + console.log(a); // undefined + console.log(b); // 1 + console.log(c); // 1 + + // good + (function example() { + let a = 1; + let b = a; + let c = a; + }()); + + console.log(a); // undefined + console.log(b); // undefined + console.log(c); // undefined +}()); + + +// eslint: no-unused-vars +(function() { + // bad + const a = 1; + +}()); diff --git a/linters/tests/whitespace.js b/linters/tests/whitespace.js index 67ad74bbf5..ec9a1f69c3 100644 --- a/linters/tests/whitespace.js +++ b/linters/tests/whitespace.js @@ -1,3 +1,5 @@ +/* eslint no-unused-vars: 0 */ + // https://github.com/thenerdery/javascript-standards#whitespace--spaces // eslint: indent (function() { @@ -151,7 +153,7 @@ }()); // https://github.com/thenerdery/javascript-standards#whitespace--after-blocks -// eslint: ??? +// eslint: (no known rule enforcing this exists) (function() { const foo = true; const bar = true; @@ -363,5 +365,13 @@ const foo = 1; }()); +// eslint: rest-spread-spacing +(function() { + // bad + const bar = function() {}; + const foo = [1,2,3]; + bar(... foo); +}()); + // https://github.com/thenerdery/javascript-standards#whitespace--newline-at-end // eslint: no-trailing-spaces \ No newline at end of file diff --git a/package.json b/package.json index f14610ecae..f97092fb1d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nerdery-javascript-standards", "description": "Nerdery JavaScript Standards", - "version": "2.0.0", + "version": "2.1.0", "repository": { "type": "git", "url": "https://github.com/thenerdery/javascript-standards.git"