From 1dfcde6a6a1a2fa6cbae11c42e75bbcfa442d949 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Wed, 3 Jun 2015 17:14:11 -0400 Subject: [PATCH 01/71] Update README.md needs moar hudl --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5a11988c6f..e14c86f203 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/airbnb/javascript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - -# Airbnb JavaScript Style Guide() { +# Hudl JavaScript Style Guide() { *A mostly reasonable approach to JavaScript* +Forked from [AirBNB's style guide](https://github.com/airbnb/javascript) + [For the ES5-only guide click here](es5/). ## Table of Contents From caa54b890ff12c1675dcaf862a37afc59b69e725 Mon Sep 17 00:00:00 2001 From: Brian Kaiser Date: Tue, 7 Jul 2015 12:58:09 -0400 Subject: [PATCH 02/71] Move to react/sort-comp defaults in ESLint * the newest version of react plugin handles the defaults much better so the override isn't necessary --- linters/.eslintrc | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index 93b84a54fe..33f0790190 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -188,25 +188,6 @@ "react/react-in-jsx-scope": 2, "react/self-closing-comp": 2, "react/wrap-multilines": 2, - "react/sort-comp": [2, { - "order": [ - "displayName", - "mixins", - "statics", - "propTypes", - "getDefaultProps", - "getInitialState", - "componentWillMount", - "componentDidMount", - "componentWillReceiveProps", - "shouldComponentUpdate", - "componentWillUpdate", - "componentWillUnmount", - "/^on.+$/", - "/^get.+$/", - "/^render.+$/", - "render" - ] - }] + "react/sort-comp": 2, } } From caf8eb4b6463cb853330a82067cd1d7e3aa6b001 Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Wed, 8 Jul 2015 09:41:12 -0500 Subject: [PATCH 03/71] Remove newCap rule Lee Byron makes a good point here: https://github.com/eslint/eslint/issues/2023#issuecomment-80255655 the linked article is specifically focused on Immutablejs, which I'm using, and will probably be used in other React projects. So this would be a normal issue potentially for us. --- linters/.eslintrc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index 33f0790190..d134b96e82 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -143,9 +143,7 @@ "beforeColon": false, "afterColon": true }], - "new-cap": [2, { // http://eslint.org/docs/rules/new-cap - "newIsCap": true - }], + "new-cap": 0, // http://eslint.org/docs/rules/new-cap "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines "max": 2 }], From 3dc73d76c5b0c4c20636d2ce9795c3b722259c51 Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Thu, 9 Jul 2015 09:53:19 -0500 Subject: [PATCH 04/71] Update .eslintrc --- linters/.eslintrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index d134b96e82..4352988f2b 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -143,7 +143,10 @@ "beforeColon": false, "afterColon": true }], - "new-cap": 0, // http://eslint.org/docs/rules/new-cap + "new-cap": [2, { // http://eslint.org/docs/rules/new-cap + "newIsCap": true, + "capIsNew": false + }], "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines "max": 2 }], From 76bbc15360e6cd3231791645d6df029666f7926f Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Thu, 23 Jul 2015 10:50:06 -0400 Subject: [PATCH 05/71] fix merge conflict resolution mistake --- linters/.eslintrc | 1 - 1 file changed, 1 deletion(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index 5930de5cbd..fe4248536e 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -190,6 +190,5 @@ "react/self-closing-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md "react/wrap-multilines": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md "react/sort-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md - }] } } From 34030052d2ab83746ff44bd971515ed07a782f80 Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Fri, 2 Oct 2015 13:53:14 -0500 Subject: [PATCH 06/71] Eslint 1.0 changes --- linters/.eslintrc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index fe4248536e..461765fd77 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -69,9 +69,9 @@ "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls - "no-reserved-keys": 2, // http://eslint.org/docs/rules/no-reserved-keys "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable + "quote-props": [2, "consistent"],// http://eslint.org/docs/rules/quote-props.html "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var @@ -147,6 +147,7 @@ "newIsCap": true, "capIsNew": false }], + "no-extra-parens": 2, // http://eslint.org/docs/rules/no-extra-parens.html "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines "max": 2 }], @@ -154,7 +155,6 @@ "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces - "no-wrap-func": 2, // http://eslint.org/docs/rules/no-wrap-func "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks @@ -168,7 +168,7 @@ "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case - "spaced-line-comment": 2, // http://eslint.org/docs/rules/spaced-line-comment + "spaced-comment": 2, // http://eslint.org/docs/rules/spaced-comment /** * JSX style From 09c745d17e58bae8c32fe8d69d54e2342c6a80b8 Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Fri, 2 Oct 2015 15:09:46 -0500 Subject: [PATCH 07/71] react/jsx-quotes deprecated for jsx-quotes --- linters/.eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index 461765fd77..6bd98a6d6a 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -139,6 +139,7 @@ "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style "eol-last": 2, // http://eslint.org/docs/rules/eol-last "func-names": 1, // http://eslint.org/docs/rules/func-names + "jsx-quotes": 2, // http://eslint.org/docs/rules/jsx-quotes "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing "beforeColon": false, "afterColon": true @@ -175,7 +176,6 @@ */ "react/display-name": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md "react/jsx-boolean-value": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md - "react/jsx-quotes": [2, "double"], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-quotes.md "react/jsx-no-undef": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md "react/jsx-sort-props": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md "react/jsx-sort-prop-types": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-prop-types.md From 47e49f1cae2787be1fc48e84f776b80795367295 Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Wed, 16 Dec 2015 11:48:13 -0600 Subject: [PATCH 08/71] Use export default with class name if possible --- react/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/react/README.md b/react/README.md index 3c01981f8c..3c296d18db 100644 --- a/react/README.md +++ b/react/README.md @@ -89,6 +89,11 @@ } export default ReservationCard; + + + // better + export default class ReservationCard extends React.Component { + } ``` ## Alignment From a558559e3f4a2123a892e22807e71a19e68c493c Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Thu, 17 Dec 2015 11:12:06 -0600 Subject: [PATCH 09/71] Make export default the good way --- react/README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/react/README.md b/react/README.md index 3c296d18db..77c9d088b4 100644 --- a/react/README.md +++ b/react/README.md @@ -85,13 +85,6 @@ }); // good - class ReservationCard extends React.Component { - } - - export default ReservationCard; - - - // better export default class ReservationCard extends React.Component { } ``` From fdc0fe0aba10cd56f97c80b1bcbef78602f45b29 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Dec 2015 13:13:42 -0500 Subject: [PATCH 10/71] Update jshintrc to allow 120 chars per line --- linters/jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linters/jshintrc b/linters/jshintrc index 141067fd23..ee68dbd56d 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -35,7 +35,7 @@ "latedef": true, // Enforce line length to 80 characters - "maxlen": 80, + "maxlen": 120, // Require capitalized names for constructor functions. "newcap": true, From fbef93a4badd4b8ac3e1227a669774977ffa8521 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Dec 2015 13:15:49 -0500 Subject: [PATCH 11/71] Update SublimeLinter to allow 120 chars per line --- linters/SublimeLinter/SublimeLinter.sublime-settings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linters/SublimeLinter/SublimeLinter.sublime-settings b/linters/SublimeLinter/SublimeLinter.sublime-settings index 12360f3f1c..0c1707654c 100644 --- a/linters/SublimeLinter/SublimeLinter.sublime-settings +++ b/linters/SublimeLinter/SublimeLinter.sublime-settings @@ -64,8 +64,8 @@ // Warn when variables are defined but never used. "unused": true, - // Enforce line length to 80 characters - "maxlen": 80, + // Enforce line length to 120 characters + "maxlen": 120, // Enforce placing 'use strict' at the top function scope "strict": true From 0ac6dc81842b838022cd3c53033650ed3e2484ce Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Dec 2015 13:16:13 -0500 Subject: [PATCH 12/71] fix comment in jshintrc --- linters/jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linters/jshintrc b/linters/jshintrc index ee68dbd56d..5e3ece8933 100644 --- a/linters/jshintrc +++ b/linters/jshintrc @@ -34,7 +34,7 @@ // Prohibit use of a variable before it is defined. "latedef": true, - // Enforce line length to 80 characters + // Enforce line length to 120 characters "maxlen": 120, // Require capitalized names for constructor functions. From c2857bc9909a8eaad84eea6cea951a9759daf677 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Dec 2015 13:20:04 -0500 Subject: [PATCH 13/71] update .eslintrc to enforce 120 chars per line --- linters/.eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/linters/.eslintrc b/linters/.eslintrc index 6bd98a6d6a..eca07e4436 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -78,6 +78,7 @@ /** * Best practices */ + "max-len": [2, 120, 4], // http://eslint.org/docs/rules/max-len.html "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly "default-case": 2, // http://eslint.org/docs/rules/default-case From 5fcb6f9d5ea301a4cb2092a8074d9480152a3397 Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Tue, 5 Jan 2016 10:14:31 -0600 Subject: [PATCH 14/71] Add usage of arrow functions in react --- react/README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/react/README.md b/react/README.md index 77c9d088b4..afbe494f6f 100644 --- a/react/README.md +++ b/react/README.md @@ -219,7 +219,7 @@ ```javascript // bad React.createClass({ - _onClickSubmit() { + _myComponentMethod() { // do stuff } @@ -228,7 +228,7 @@ // good class extends React.Component { - onClickSubmit() { + myComponentMethod() { // do stuff } @@ -236,6 +236,30 @@ }); ``` +## Arrow Functions + - When using ES2015 syntax and declaring your components as `class MyComponent extends React.Components {}` you should use arrow functions to define functions that will need to be bound to the components scope. This removes the need to have `.bind()` ran on every render. The arrow function will have the lexical `this` of the component. + ```javascript + // bad + onClick() { + // do stuff + } + + render() { + return Clicky Link; + } + + // good + onClick = () => { + // do stuff + } + + render() { + return Clickier Link; + } + ``` + + For more information, please checkout the "Arrow Functions" section of [this article on ES2015+ React](http://babeljs.io/blog/2015/06/07/react-on-es6-plus/). + ## Ordering - Ordering for class extends React.Component: From 28707ff0a8bbabc3f9f725a27281e95f34cdd39d Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Tue, 5 Jan 2016 10:19:42 -0600 Subject: [PATCH 15/71] Add link to table of contents --- react/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/react/README.md b/react/README.md index afbe494f6f..ebef249ed1 100644 --- a/react/README.md +++ b/react/README.md @@ -14,6 +14,7 @@ 1. [Parentheses](#parentheses) 1. [Tags](#tags) 1. [Methods](#methods) + 1. [Arrow Functions](#arrow-functions) 1. [Ordering](#ordering) ## Basic Rules @@ -245,7 +246,7 @@ } render() { - return Clicky Link; + return Clicky; } // good @@ -254,7 +255,7 @@ } render() { - return Clickier Link; + return Clickier; } ``` @@ -263,7 +264,7 @@ ## Ordering - Ordering for class extends React.Component: - + 1. constructor 1. optional static methods 1. getChildContext From 9eeaa537520b26958d581af5037bfe33818a74b8 Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Tue, 5 Jan 2016 10:29:31 -0600 Subject: [PATCH 16/71] Clarity --- react/README.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/react/README.md b/react/README.md index ebef249ed1..5b5dd09d86 100644 --- a/react/README.md +++ b/react/README.md @@ -241,21 +241,25 @@ - When using ES2015 syntax and declaring your components as `class MyComponent extends React.Components {}` you should use arrow functions to define functions that will need to be bound to the components scope. This removes the need to have `.bind()` ran on every render. The arrow function will have the lexical `this` of the component. ```javascript // bad - onClick() { - // do stuff - } + class MyComponent extends React.Component { + onLinkClick() { + // do stuff + } - render() { - return Clicky; + render() { + return Clicky; + } } // good - onClick = () => { - // do stuff - } + class MyComponent extends React.Component { + onLinkClick = () => { + // do stuff + } - render() { - return Clickier; + render() { + return Clicky; + } } ``` From 38713a4455d4eaa35ea80d1234a1c04deb7e79df Mon Sep 17 00:00:00 2001 From: Cole Voss Date: Tue, 5 Jan 2016 16:00:39 -0600 Subject: [PATCH 17/71] Fix different fn names --- react/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/react/README.md b/react/README.md index 5b5dd09d86..5144452fcc 100644 --- a/react/README.md +++ b/react/README.md @@ -247,7 +247,7 @@ } render() { - return Clicky; + return Clicky; } } @@ -258,7 +258,7 @@ } render() { - return Clicky; + return Clicky; } } ``` From e47b796863868c8906f2c76c2ceb203aa85df461 Mon Sep 17 00:00:00 2001 From: Brandon Bone Date: Fri, 15 Jan 2016 14:27:33 -0800 Subject: [PATCH 18/71] removed no-extra-parens as it conflicts with our jsx multiline return standard --- linters/.eslintrc | 1 - 1 file changed, 1 deletion(-) diff --git a/linters/.eslintrc b/linters/.eslintrc index eca07e4436..8d70c79f7f 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -149,7 +149,6 @@ "newIsCap": true, "capIsNew": false }], - "no-extra-parens": 2, // http://eslint.org/docs/rules/no-extra-parens.html "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines "max": 2 }], From 6176e2e13e0482092fe41908729d742d13cd818a Mon Sep 17 00:00:00 2001 From: Brandon Bone Date: Fri, 15 Jan 2016 16:27:20 -0800 Subject: [PATCH 19/71] updated no-extra-parens value to allow jsx paren-wrapped multireturns through --- linters/.eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/linters/.eslintrc b/linters/.eslintrc index 8d70c79f7f..956ac91222 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -149,6 +149,7 @@ "newIsCap": true, "capIsNew": false }], + "no-extra-parens": [2, "functions"], // http://eslint.org/docs/rules/no-extra-parens.html "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines "max": 2 }], From cf9e05b429c9f37698baec79521a5564c78fece0 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Mon, 1 Feb 2016 23:51:08 -0700 Subject: [PATCH 20/71] Adjust updates and rename airbnb -> hudl - Incorporate updates and adjust for publishing as a hudl package - Adding in some gulp task stubs to expand on --- packages/eslint-config-airbnb/.eslintrc | 8 -- packages/eslint-config-airbnb/base.js | 7 -- packages/eslint-config-airbnb/index.js | 8 -- packages/eslint-config-airbnb/legacy.js | 20 ----- .../node_modules/eslint-config-airbnb | 1 - packages/eslint-config-airbnb/package.json | 51 ------------ packages/eslint-config-hudl/.eslintrc | 3 + packages/eslint-config-hudl/.npmrc | 1 + .../CHANGELOG.md | 0 .../README.md | 0 packages/eslint-config-hudl/base.js | 7 ++ packages/eslint-config-hudl/gulpfile.js | 1 + packages/eslint-config-hudl/index.js | 8 ++ packages/eslint-config-hudl/legacy.js | 20 +++++ packages/eslint-config-hudl/package.json | 77 +++++++++++++++++++ .../rules/.eslintrc.json | 0 .../rules/best-practices.js | 17 ++-- .../rules/errors.js | 4 +- .../rules/es6.js | 13 ++-- .../rules/legacy.js | 4 +- .../rules/node.js | 6 +- .../rules/react.js | 53 +++++++++---- .../rules/strict.js | 4 +- .../rules/style.js | 58 ++++++++++---- .../rules/variables.js | 9 ++- packages/eslint-config-hudl/tasks/.eslintrc | 10 +++ .../eslint-config-hudl/tasks/config/index.js | 16 ++++ packages/eslint-config-hudl/tasks/lint.js | 29 +++++++ packages/eslint-config-hudl/tasks/test.js | 65 ++++++++++++++++ .../test/.eslintrc | 0 .../test/test-base.js | 2 +- .../test/test-react-order.js | 4 +- 32 files changed, 356 insertions(+), 150 deletions(-) delete mode 100644 packages/eslint-config-airbnb/.eslintrc delete mode 100644 packages/eslint-config-airbnb/base.js delete mode 100644 packages/eslint-config-airbnb/index.js delete mode 100644 packages/eslint-config-airbnb/legacy.js delete mode 120000 packages/eslint-config-airbnb/node_modules/eslint-config-airbnb delete mode 100644 packages/eslint-config-airbnb/package.json create mode 100644 packages/eslint-config-hudl/.eslintrc create mode 100644 packages/eslint-config-hudl/.npmrc rename packages/{eslint-config-airbnb => eslint-config-hudl}/CHANGELOG.md (100%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/README.md (100%) create mode 100644 packages/eslint-config-hudl/base.js create mode 100644 packages/eslint-config-hudl/gulpfile.js create mode 100644 packages/eslint-config-hudl/index.js create mode 100644 packages/eslint-config-hudl/legacy.js create mode 100644 packages/eslint-config-hudl/package.json rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/.eslintrc.json (100%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/best-practices.js (94%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/errors.js (98%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/es6.js (93%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/legacy.js (94%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/node.js (94%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/react.js (89%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/strict.js (70%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/style.js (83%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/rules/variables.js (88%) create mode 100644 packages/eslint-config-hudl/tasks/.eslintrc create mode 100644 packages/eslint-config-hudl/tasks/config/index.js create mode 100644 packages/eslint-config-hudl/tasks/lint.js create mode 100644 packages/eslint-config-hudl/tasks/test.js rename packages/{eslint-config-airbnb => eslint-config-hudl}/test/.eslintrc (100%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/test/test-base.js (96%) rename packages/{eslint-config-airbnb => eslint-config-hudl}/test/test-react-order.js (98%) diff --git a/packages/eslint-config-airbnb/.eslintrc b/packages/eslint-config-airbnb/.eslintrc deleted file mode 100644 index 4b3b1fa429..0000000000 --- a/packages/eslint-config-airbnb/.eslintrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "airbnb", - "rules": { - // 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 - } -} diff --git a/packages/eslint-config-airbnb/base.js b/packages/eslint-config-airbnb/base.js deleted file mode 100644 index 1cfea52161..0000000000 --- a/packages/eslint-config-airbnb/base.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - extends: [ - 'eslint-config-airbnb/legacy', - 'eslint-config-airbnb/rules/es6', - ].map(require.resolve), - rules: {} -}; diff --git a/packages/eslint-config-airbnb/index.js b/packages/eslint-config-airbnb/index.js deleted file mode 100644 index e9ce995ae5..0000000000 --- a/packages/eslint-config-airbnb/index.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - extends: [ - 'eslint-config-airbnb/base', - 'eslint-config-airbnb/rules/strict', - 'eslint-config-airbnb/rules/react', - ].map(require.resolve), - rules: {} -}; diff --git a/packages/eslint-config-airbnb/legacy.js b/packages/eslint-config-airbnb/legacy.js deleted file mode 100644 index b404cf7c88..0000000000 --- a/packages/eslint-config-airbnb/legacy.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - extends: [ - 'eslint-config-airbnb/rules/best-practices', - 'eslint-config-airbnb/rules/errors', - 'eslint-config-airbnb/rules/legacy', - 'eslint-config-airbnb/rules/node', - 'eslint-config-airbnb/rules/style', - 'eslint-config-airbnb/rules/variables' - ].map(require.resolve), - env: { - browser: true, - node: true, - amd: false, - mocha: false, - jasmine: false - }, - ecmaFeatures: {}, - globals: {}, - rules: {} -}; diff --git a/packages/eslint-config-airbnb/node_modules/eslint-config-airbnb b/packages/eslint-config-airbnb/node_modules/eslint-config-airbnb deleted file mode 120000 index a96aa0ea9d..0000000000 --- a/packages/eslint-config-airbnb/node_modules/eslint-config-airbnb +++ /dev/null @@ -1 +0,0 @@ -.. \ No newline at end of file diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json deleted file mode 100644 index 63439f6b62..0000000000 --- a/packages/eslint-config-airbnb/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "eslint-config-airbnb", - "version": "4.0.0", - "description": "Airbnb's ESLint config, following our styleguide", - "main": "index.js", - "scripts": { - "lint": "eslint .", - "tests-only": "babel-tape-runner ./test/test-*.js", - "test": "parallelshell 'npm run lint' 'npm run tests-only'" - }, - "repository": { - "type": "git", - "url": "https://github.com/airbnb/javascript" - }, - "keywords": [ - "eslint", - "eslintconfig", - "config", - "airbnb", - "javascript", - "styleguide" - ], - "author": "Jake Teton-Landis (https://twitter.com/@jitl)", - "contributors": [ - { - "name": "Jake Teton-Landis", - "url": "https://twitter.com/jitl" - }, - { - "name": "Jordan Harband", - "email": "ljharb@gmail.com", - "url": "http://ljharb.codes" - } - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/airbnb/javascript/issues" - }, - "homepage": "https://github.com/airbnb/javascript", - "devDependencies": { - "babel-tape-runner": "1.2.0", - "eslint": "^1.10.3", - "eslint-plugin-react": "^3.12.0", - "react": "^0.13.3", - "tape": "^4.2.2", - "parallelshell": "^2.0.0" - }, - "peerDependencies": { - "eslint": ">=1.0.0" - } -} diff --git a/packages/eslint-config-hudl/.eslintrc b/packages/eslint-config-hudl/.eslintrc new file mode 100644 index 0000000000..d811f404b4 --- /dev/null +++ b/packages/eslint-config-hudl/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "./index.js" +} diff --git a/packages/eslint-config-hudl/.npmrc b/packages/eslint-config-hudl/.npmrc new file mode 100644 index 0000000000..80e3bd191c --- /dev/null +++ b/packages/eslint-config-hudl/.npmrc @@ -0,0 +1 @@ +registry=http://npm.thorhudl.com diff --git a/packages/eslint-config-airbnb/CHANGELOG.md b/packages/eslint-config-hudl/CHANGELOG.md similarity index 100% rename from packages/eslint-config-airbnb/CHANGELOG.md rename to packages/eslint-config-hudl/CHANGELOG.md diff --git a/packages/eslint-config-airbnb/README.md b/packages/eslint-config-hudl/README.md similarity index 100% rename from packages/eslint-config-airbnb/README.md rename to packages/eslint-config-hudl/README.md diff --git a/packages/eslint-config-hudl/base.js b/packages/eslint-config-hudl/base.js new file mode 100644 index 0000000000..fa4c50ebcd --- /dev/null +++ b/packages/eslint-config-hudl/base.js @@ -0,0 +1,7 @@ +module.exports = { + extends: [ + './legacy', + './rules/es6', + ].map(require.resolve), + rules: {}, +}; diff --git a/packages/eslint-config-hudl/gulpfile.js b/packages/eslint-config-hudl/gulpfile.js new file mode 100644 index 0000000000..59e430a792 --- /dev/null +++ b/packages/eslint-config-hudl/gulpfile.js @@ -0,0 +1 @@ +require('require-dir')('./tasks'); diff --git a/packages/eslint-config-hudl/index.js b/packages/eslint-config-hudl/index.js new file mode 100644 index 0000000000..01d92530f8 --- /dev/null +++ b/packages/eslint-config-hudl/index.js @@ -0,0 +1,8 @@ +module.exports = { + extends: [ + './base', + './rules/strict', + './rules/react', + ].map(require.resolve), + rules: {}, +}; diff --git a/packages/eslint-config-hudl/legacy.js b/packages/eslint-config-hudl/legacy.js new file mode 100644 index 0000000000..d8df06dc0d --- /dev/null +++ b/packages/eslint-config-hudl/legacy.js @@ -0,0 +1,20 @@ +module.exports = { + extends: [ + './rules/best-practices', + './rules/errors', + './rules/legacy', + './rules/node', + './rules/style', + './rules/variables', + ].map(require.resolve), + env: { + browser: true, + node: true, + amd: false, + mocha: false, + jasmine: false, + }, + ecmaFeatures: {}, + globals: {}, + rules: {}, +}; diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json new file mode 100644 index 0000000000..77a124346d --- /dev/null +++ b/packages/eslint-config-hudl/package.json @@ -0,0 +1,77 @@ +{ + "name": "eslint-config-hudl", + "version": "4.0.0", + "description": "Hudl's ESLint config, following our styleguide", + "main": "index.js", + "scripts": { + "tests-only": "babel-tape-runner ./test/test-*.js", + "test": "gulp test" + }, + "repository": { + "type": "git", + "url": "https://github.com/hudl/javascript" + }, + "keywords": [ + "eslint", + "eslintconfig", + "config", + "airbnb", + "javascript", + "styleguide" + ], + "author": "Jake Teton-Landis (https://twitter.com/@jitl)", + "contributors": [ + { + "name": "Jake Teton-Landis", + "url": "https://twitter.com/jitl" + }, + { + "name": "Jordan Harband", + "email": "ljharb@gmail.com", + "url": "http://ljharb.codes" + } + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/hudl/javascript/issues" + }, + "homepage": "https://github.com/hudl/javascript", + "publishConfig": { + "registry": "http://npm.thorhudl.com" + }, + "hudl-ci": { + "buildCommand": null, + "lintCommand": "./node_modules/.bin/gulp lint", + "testCommand": "./node_modules/.bin/gulp test" + }, + "tasksConfig": { + "test": { + "src": [ + "lib/**/*.js", + "!**/__specs__/**/*.js" + ], + "tests": "**/*-specs.js", + "setup": "./test/setup", + "coverageThresholds": { + "global": 100 + } + } + }, + "devDependencies": { + "babel-tape-runner": "1.2.0", + "eslint": "^1.10.3", + "eslint-plugin-react": "^3.12.0", + "fs-extra": "^0.26.5", + "gulp": "^3.9.0", + "gulp-eslint": "^1.1.1", + "gulp-if": "^2.0.0", + "gulp-istanbul": "^0.10.3", + "gulp-mocha": "^2.2.0", + "react": "^0.13.3", + "require-dir": "^0.3.0", + "tape": "^4.2.2" + }, + "peerDependencies": { + "eslint": ">=1.0.0" + } +} diff --git a/packages/eslint-config-airbnb/rules/.eslintrc.json b/packages/eslint-config-hudl/rules/.eslintrc.json similarity index 100% rename from packages/eslint-config-airbnb/rules/.eslintrc.json rename to packages/eslint-config-hudl/rules/.eslintrc.json diff --git a/packages/eslint-config-airbnb/rules/best-practices.js b/packages/eslint-config-hudl/rules/best-practices.js similarity index 94% rename from packages/eslint-config-airbnb/rules/best-practices.js rename to packages/eslint-config-hudl/rules/best-practices.js index c2af1b7875..dfb1ada5f6 100644 --- a/packages/eslint-config-airbnb/rules/best-practices.js +++ b/packages/eslint-config-hudl/rules/best-practices.js @@ -13,7 +13,9 @@ module.exports = { // require default case in switch statements 'default-case': 2, // encourages use of dot notation whenever possible - 'dot-notation': [2, { 'allowKeywords': true }], + 'dot-notation': [2, { + 'allowKeywords': true, + }], // enforces consistent newlines before or after dots 'dot-location': 0, // require the use of === and !== @@ -76,7 +78,9 @@ module.exports = { // disallow reassignment of function parameters // disallow parameter object manipulation // rule: http://eslint.org/docs/rules/no-param-reassign.html - 'no-param-reassign': [2, { 'props': true }], + 'no-param-reassign': [2, { + 'props': true, + }], // disallow use of process.env 'no-process-env': 0, // disallow usage of __proto__ property @@ -100,7 +104,10 @@ module.exports = { // disallow use of void operator 'no-void': 0, // disallow usage of configurable warning terms in comments: e.g. todo - 'no-warning-comments': [0, { 'terms': ['todo', 'fixme', 'xxx'], 'location': 'start' }], + 'no-warning-comments': [0, { + 'terms': ['todo', 'fixme', 'xxx'], + 'location': 'start', + }], // disallow use of the with statement 'no-with': 2, // require use of the second argument for parseInt() @@ -111,6 +118,6 @@ module.exports = { // http://eslint.org/docs/rules/wrap-iife.html 'wrap-iife': [2, 'outside'], // require or disallow Yoda conditions - 'yoda': 2 - } + 'yoda': 2, + }, }; diff --git a/packages/eslint-config-airbnb/rules/errors.js b/packages/eslint-config-hudl/rules/errors.js similarity index 98% rename from packages/eslint-config-airbnb/rules/errors.js rename to packages/eslint-config-hudl/rules/errors.js index ec1b1aab0e..2b55560f0b 100644 --- a/packages/eslint-config-airbnb/rules/errors.js +++ b/packages/eslint-config-hudl/rules/errors.js @@ -55,6 +55,6 @@ module.exports = { // ensure that the results of typeof are compared against a valid string 'valid-typeof': 2, // Avoid code that looks like two expressions but is actually one - 'no-unexpected-multiline': 0 - } + 'no-unexpected-multiline': 0, + }, }; diff --git a/packages/eslint-config-airbnb/rules/es6.js b/packages/eslint-config-hudl/rules/es6.js similarity index 93% rename from packages/eslint-config-airbnb/rules/es6.js rename to packages/eslint-config-hudl/rules/es6.js index e34684346d..27ecfdb00b 100644 --- a/packages/eslint-config-airbnb/rules/es6.js +++ b/packages/eslint-config-hudl/rules/es6.js @@ -1,6 +1,6 @@ module.exports = { 'env': { - 'es6': false + 'es6': false, }, 'ecmaFeatures': { 'arrowFunctions': true, @@ -19,7 +19,7 @@ module.exports = { 'spread': true, 'superInFunctions': true, 'templateStrings': true, - 'jsx': true + 'jsx': true, }, 'rules': { // enforces no braces where they can be omitted @@ -29,7 +29,10 @@ module.exports = { 'arrow-parens': 0, // require space before/after arrow function's arrow // https://github.com/eslint/eslint/blob/master/docs/rules/arrow-spacing.md - 'arrow-spacing': [2, { 'before': true, 'after': true }], + 'arrow-spacing': [2, { + 'before': true, + 'after': true, + }], // verify super() callings in constructors 'constructor-super': 0, // enforce the spacing around the * in generator functions @@ -57,6 +60,6 @@ module.exports = { // http://eslint.org/docs/rules/prefer-template 'prefer-template': 2, // disallow generator functions that do not have yield - 'require-yield': 0 - } + 'require-yield': 0, + }, }; diff --git a/packages/eslint-config-airbnb/rules/legacy.js b/packages/eslint-config-hudl/rules/legacy.js similarity index 94% rename from packages/eslint-config-airbnb/rules/legacy.js rename to packages/eslint-config-hudl/rules/legacy.js index e94c774f26..fac7b23c07 100644 --- a/packages/eslint-config-airbnb/rules/legacy.js +++ b/packages/eslint-config-hudl/rules/legacy.js @@ -9,6 +9,6 @@ module.exports = { // disallow use of bitwise operators 'no-bitwise': 0, // disallow use of unary operators, ++ and -- - 'no-plusplus': 0 - } + 'no-plusplus': 0, + }, }; diff --git a/packages/eslint-config-airbnb/rules/node.js b/packages/eslint-config-hudl/rules/node.js similarity index 94% rename from packages/eslint-config-airbnb/rules/node.js rename to packages/eslint-config-hudl/rules/node.js index 16b6f20d45..f8ace7b708 100644 --- a/packages/eslint-config-airbnb/rules/node.js +++ b/packages/eslint-config-hudl/rules/node.js @@ -1,6 +1,6 @@ module.exports = { 'env': { - 'node': true + 'node': true, }, 'rules': { // enforce return after a callback @@ -18,6 +18,6 @@ module.exports = { // restrict usage of specified node modules 'no-restricted-modules': 0, // disallow use of synchronous methods (off by default) - 'no-sync': 0 - } + 'no-sync': 0, + }, }; diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-hudl/rules/react.js similarity index 89% rename from packages/eslint-config-airbnb/rules/react.js rename to packages/eslint-config-hudl/rules/react.js index e1e1c25993..62b16aeda0 100644 --- a/packages/eslint-config-airbnb/rules/react.js +++ b/packages/eslint-config-hudl/rules/react.js @@ -1,19 +1,23 @@ module.exports = { 'plugins': [ - 'react' + 'react', ], 'ecmaFeatures': { - 'jsx': true + 'jsx': true, }, // View link below for react rules documentation // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules 'rules': { // Prevent missing displayName in a React component definition // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md - 'react/display-name': [0, { 'acceptTranspilerName': false }], + 'react/display-name': [0, { + 'acceptTranspilerName': false, + }], // Forbid certain propTypes (any, array, object) // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md - 'react/forbid-prop-types': [0, { 'forbid': ['any', 'array', 'object'] }], + 'react/forbid-prop-types': [0, { + 'forbid': ['any', 'array', 'object'], + }], // Enforce boolean attributes notation in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md 'react/jsx-boolean-value': [2, 'never'], @@ -22,7 +26,9 @@ module.exports = { 'react/jsx-closing-bracket-location': [2, 'line-aligned'], // Enforce or disallow spaces inside of curly braces in JSX attributes // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md - 'react/jsx-curly-spacing': [0, 'never', { 'allowMultiline': true }], + 'react/jsx-curly-spacing': [0, 'never', { + 'allowMultiline': true, + }], // Enforce event handler naming conventions in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md 'react/jsx-handler-names': [0, { @@ -37,13 +43,17 @@ module.exports = { 'react/jsx-key': 0, // Limit maximum of props on a single line in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md - 'react/jsx-max-props-per-line': [0, { 'maximum': 1 }], + 'react/jsx-max-props-per-line': [0, { + 'maximum': 1, + }], // Prevent usage of .bind() and arrow functions in JSX props // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 'react/jsx-no-bind': 2, // Prevent duplicate props in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md - 'react/jsx-no-duplicate-props': [0, { 'ignoreCase': false }], + 'react/jsx-no-duplicate-props': [0, { + 'ignoreCase': false, + }], // Prevent usage of unwrapped JSX strings // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md 'react/jsx-no-literals': 0, @@ -67,7 +77,9 @@ module.exports = { }], // Prevent React to be incorrectly marked as unused // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md - 'react/jsx-uses-react': [2, { 'pragma': 'React' }], + 'react/jsx-uses-react': [2, { + 'pragma': 'React', + }], // Prevent variables used in JSX to be incorrectly marked as unused // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md 'react/jsx-uses-vars': 2, @@ -76,7 +88,9 @@ module.exports = { 'react/no-danger': 0, // Prevent usage of deprecated methods // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md - 'react/no-deprecated': [1, { 'react': '0.14.0' }], + 'react/no-deprecated': [1, { + 'react': '0.14.0', + }], // Prevent usage of setState in componentDidMount // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md 'react/no-did-mount-set-state': [2, 'allow-in-func'], @@ -91,7 +105,9 @@ module.exports = { 'react/no-is-mounted': 2, // Prevent multiple component definition per file // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md - 'react/no-multi-comp': [2, { 'ignoreStateless': true }], + 'react/no-multi-comp': [2, { + 'ignoreStateless': true, + }], // Prevent usage of setState // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md 'react/no-set-state': 0, @@ -106,13 +122,18 @@ module.exports = { 'react/prefer-es6-class': [2, 'always'], // Prevent missing props validation in a React component definition // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md - 'react/prop-types': [2, { 'ignore': [], customValidators: [] }], + 'react/prop-types': [2, { + 'ignore': [], + customValidators: [], + }], // Prevent missing React when using JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md 'react/react-in-jsx-scope': 2, // Restrict file extensions that may be required // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-extension.md - 'react/require-extension': [0, { 'extensions': ['.jsx'] }], + 'react/require-extension': [0, { + 'extensions': ['.jsx'], + }], // Prevent extra closing tags for components without children // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md 'react/self-closing-comp': 2, @@ -125,15 +146,15 @@ module.exports = { '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', 'everything-else', '/^render.+$/', - 'render' - ] + 'render', + ], }], // Prevent missing parentheses around multilines JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md 'react/wrap-multilines': [2, { declaration: true, assignment: true, - return: true + return: true, }], - } + }, }; diff --git a/packages/eslint-config-airbnb/rules/strict.js b/packages/eslint-config-hudl/rules/strict.js similarity index 70% rename from packages/eslint-config-airbnb/rules/strict.js rename to packages/eslint-config-hudl/rules/strict.js index 6d32f8ca59..0f669c2fce 100644 --- a/packages/eslint-config-airbnb/rules/strict.js +++ b/packages/eslint-config-hudl/rules/strict.js @@ -1,6 +1,6 @@ module.exports = { 'rules': { // babel inserts `'use strict';` for us - 'strict': [2, 'never'] - } + 'strict': [2, 'never'], + }, }; diff --git a/packages/eslint-config-airbnb/rules/style.js b/packages/eslint-config-hudl/rules/style.js similarity index 83% rename from packages/eslint-config-airbnb/rules/style.js rename to packages/eslint-config-hudl/rules/style.js index 2e3e3cae1b..fd6e6e2b0d 100644 --- a/packages/eslint-config-airbnb/rules/style.js +++ b/packages/eslint-config-hudl/rules/style.js @@ -3,11 +3,18 @@ module.exports = { // enforce spacing inside array brackets 'array-bracket-spacing': [2, 'never'], // enforce one true brace style - 'brace-style': [2, '1tbs', { 'allowSingleLine': true }], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true, + }], // require camel case names - 'camelcase': [2, { 'properties': 'never' }], + 'camelcase': [2, { + 'properties': 'never', + }], // enforce spacing before and after comma - 'comma-spacing': [2, { 'before': false, 'after': true }], + 'comma-spacing': [2, { + 'before': false, + 'after': true, + }], // enforce one true comma style 'comma-style': [2, 'last'], // disallow padding inside computed properties @@ -25,26 +32,34 @@ module.exports = { 'id-length': 0, // this option sets a specific tab width for your code // https://github.com/eslint/eslint/blob/master/docs/rules/indent.md - 'indent': [2, 2, { 'SwitchCase': 1, 'VariableDeclarator': 1 }], + 'indent': [2, 2, { + 'SwitchCase': 1, + 'VariableDeclarator': 1, + }], // specify whether double or single quotes should be used in JSX attributes // http://eslint.org/docs/rules/jsx-quotes 'jsx-quotes': [2, 'prefer-double'], // enforces spacing between keys and values in object literal properties - 'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true, + }], // enforces empty lines around comments 'lines-around-comment': 0, // disallow mixed 'LF' and 'CRLF' as linebreaks 'linebreak-style': 0, // specify the maximum length of a line in your program // https://github.com/eslint/eslint/blob/master/docs/rules/max-len.md - 'max-len': [2, 100, 2, { + 'max-len': [2, 120, 2, { 'ignoreUrls': true, - 'ignoreComments': false + 'ignoreComments': false, }], // specify the maximum depth callbacks can be nested 'max-nested-callbacks': 0, // require a capital letter for constructors - 'new-cap': [2, { 'newIsCap': true }], + 'new-cap': [2, { + 'newIsCap': true, + }], // disallow the omission of parentheses when invoking a constructor with no arguments 'new-parens': 0, // allow/disallow an empty newline after var statement @@ -60,7 +75,10 @@ module.exports = { // disallow mixed spaces and tabs for indentation 'no-mixed-spaces-and-tabs': 2, // disallow multiple empty lines and only one newline at the end - 'no-multiple-empty-lines': [2, { 'max': 2, 'maxEOF': 1 }], + 'no-multiple-empty-lines': [2, { + 'max': 2, + 'maxEOF': 1, + }], // disallow nested ternary expressions 'no-nested-ternary': 2, // disallow use of the Object constructor @@ -87,13 +105,20 @@ module.exports = { 'padded-blocks': [2, 'never'], // require quotes around object literal property names // http://eslint.org/docs/rules/quote-props.html - 'quote-props': [2, 'as-needed', { 'keywords': false, 'unnecessary': true, 'numbers': false }], + 'quote-props': [2, 'as-needed', { + 'keywords': false, + 'unnecessary': true, + 'numbers': false, + }], // specify whether double or single quotes should be used 'quotes': [2, 'single', 'avoid-escape'], // require identifiers to match the provided regular expression 'id-match': 0, // enforce spacing before and after semicolons - 'semi-spacing': [2, { 'before': false, 'after': true }], + 'semi-spacing': [2, { + 'before': false, + 'after': true, + }], // require or disallow use of semicolons instead of ASI 'semi': [2, 'always'], // sort variables within the same declaration block @@ -106,7 +131,10 @@ module.exports = { 'space-before-blocks': 2, // require or disallow space before function opening parenthesis // https://github.com/eslint/eslint/blob/master/docs/rules/space-before-function-paren.md - 'space-before-function-paren': [2, { 'anonymous': 'always', 'named': 'never' }], + 'space-before-function-paren': [2, { + 'anonymous': 'never', + 'named': 'never', + }], // require or disallow spaces inside parentheses 'space-in-parens': [2, 'never'], // require spaces around operators @@ -118,9 +146,9 @@ module.exports = { // require or disallow a space immediately following the // or /* in a comment 'spaced-comment': [2, 'always', { 'exceptions': ['-', '+'], - 'markers': ['=', '!'] // space here to support sprockets directives + 'markers': ['=', '!'], // space here to support sprockets directives }], // require regex literals to be wrapped in parentheses - 'wrap-regex': 0 - } + 'wrap-regex': 0, + }, }; diff --git a/packages/eslint-config-airbnb/rules/variables.js b/packages/eslint-config-hudl/rules/variables.js similarity index 88% rename from packages/eslint-config-airbnb/rules/variables.js rename to packages/eslint-config-hudl/rules/variables.js index 59914313f9..848e8e6a1d 100644 --- a/packages/eslint-config-airbnb/rules/variables.js +++ b/packages/eslint-config-hudl/rules/variables.js @@ -19,8 +19,11 @@ module.exports = { // disallow use of undefined variable 'no-undefined': 0, // disallow declaration of variables that are not used in the code - 'no-unused-vars': [2, { 'vars': 'local', 'args': 'after-used' }], + 'no-unused-vars': [2, { + 'vars': 'local', + 'args': 'after-used', + }], // disallow use of variables before they are defined - 'no-use-before-define': 2 - } + 'no-use-before-define': 2, + }, }; diff --git a/packages/eslint-config-hudl/tasks/.eslintrc b/packages/eslint-config-hudl/tasks/.eslintrc new file mode 100644 index 0000000000..a2fdaad018 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/.eslintrc @@ -0,0 +1,10 @@ +{ + "extends": "../legacy.js", + "rules": { + "func-names": 0 + }, + "env": { + "node": true + }, + "root": true +} diff --git a/packages/eslint-config-hudl/tasks/config/index.js b/packages/eslint-config-hudl/tasks/config/index.js new file mode 100644 index 0000000000..8827aa3088 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/config/index.js @@ -0,0 +1,16 @@ +// Pull basic config settings from package.json +// Could also check an env variable for override or programmatic creation + +var path = require('path'); + +var configKey = 'tasksConfig'; + +var packageJson = require(path.resolve('package.json')); + +var config = packageJson[configKey]; + +if (!config) { + throw new Error('Gulp task configuration not found. Looking for `' + configKey + '` property in package.json.'); +} + +module.exports = config; diff --git a/packages/eslint-config-hudl/tasks/lint.js b/packages/eslint-config-hudl/tasks/lint.js new file mode 100644 index 0000000000..6fcd694a6b --- /dev/null +++ b/packages/eslint-config-hudl/tasks/lint.js @@ -0,0 +1,29 @@ +var gulp = require('gulp'); +var eslint = require('gulp-eslint'); +var gulpIf = require('gulp-if'); + +function isFixed(file) { + // Has ESLint fixed the file contents? + return file.eslint !== null && file.eslint.fixed; +} + +gulp.task('lint', function() { + // This glob doesn't need configured because we're just pulling all local JS + // files and letting eslint handle any necessary ignores + + return gulp.src(['**/*.js', '!node_modules/**']) + // eslint() attaches the lint output to the "eslint" property + // of the file object so it can be used by other modules. + .pipe(eslint({ + // Only autofix locally so changes are committed to git + fix: !process.env.TEAMCITY_VERSION, + })) + // eslint.format() outputs the lint results to the console. + // Alternatively use eslint.formatEach() (see Docs). + .pipe(eslint.format(process.env.ESLINTFORMATTER || null)) + // Write fixes to file + .pipe(gulpIf(isFixed, gulp.dest('.'))) + // To have the process exit with an error code (1) on + // lint error, return the stream and pipe to failAfterError last. + .pipe(eslint.failAfterError()); +}); diff --git a/packages/eslint-config-hudl/tasks/test.js b/packages/eslint-config-hudl/tasks/test.js new file mode 100644 index 0000000000..8571a5ecaf --- /dev/null +++ b/packages/eslint-config-hudl/tasks/test.js @@ -0,0 +1,65 @@ +var path = require('path'); +var fs = require('fs-extra'); +var gulp = require('gulp'); +var mocha = require('gulp-mocha'); +var istanbul = require('gulp-istanbul'); +var config = require('./config').test; + +var testCoverageDir = './reports/coverage'; + +gulp.task('pre-test', function() { + return gulp.src(config.src) + // Covering files + .pipe(istanbul({ + // Include files that don't have tests yet + includeUntested: true, + })) + // Force `require` to return covered files + .pipe(istanbul.hookRequire()); +}); + +gulp.task('run-test', ['pre-test'], function() { + var stream = gulp.src(config.tests, { + read: false, + }) + .pipe(mocha({ + require: [config.setup], + // Allow TeamCity to override with custom reporter + reporter: process.env.MOCHAREPORTER || 'spec', + })) + // Creating the reports after tests run + .pipe(istanbul.writeReports({ + dir: testCoverageDir, + reporters: ['lcov', 'text'], + })); + + if (config.coverageThresholds) { + // Enforce a coverage of at least 90% + stream = stream.pipe(istanbul.enforceThresholds({ + thresholds: config.coverageThresholds, + })); + } + return stream; +}); + +gulp.task('test', ['run-test'], function() { + // Copy test coverage HTML report to more generic name for TeamCity + return new Promise(function(resolve) { + fs.move(path.join(testCoverageDir, 'lcov-report/'), './reports/tabs/test-coverage', resolve); + }).then(function() { + fs.removeSync(testCoverageDir); + }); +}); + +// Task for running tests without code coverage; intended only for getting +// more accurate line numbers for debugging test errors +gulp.task('test-debug', function() { + return gulp.src(config.tests, { + read: false, + }) + .pipe(mocha({ + require: [config.setup], + // Allow TeamCity to override with custom reporter + reporter: process.env.MOCHAREPORTER || 'spec', + })); +}); diff --git a/packages/eslint-config-airbnb/test/.eslintrc b/packages/eslint-config-hudl/test/.eslintrc similarity index 100% rename from packages/eslint-config-airbnb/test/.eslintrc rename to packages/eslint-config-hudl/test/.eslintrc diff --git a/packages/eslint-config-airbnb/test/test-base.js b/packages/eslint-config-hudl/test/test-base.js similarity index 96% rename from packages/eslint-config-airbnb/test/test-base.js rename to packages/eslint-config-hudl/test/test-base.js index 24aa884cd0..5ac9a05790 100644 --- a/packages/eslint-config-airbnb/test/test-base.js +++ b/packages/eslint-config-hudl/test/test-base.js @@ -3,7 +3,7 @@ import path from 'path'; import test from 'tape'; const files = { - base: require('../base') + base: require('../base'), }; fs.readdirSync(path.join(__dirname, '../rules')).forEach(name => { diff --git a/packages/eslint-config-airbnb/test/test-react-order.js b/packages/eslint-config-hudl/test/test-react-order.js similarity index 98% rename from packages/eslint-config-airbnb/test/test-react-order.js rename to packages/eslint-config-hudl/test/test-react-order.js index 77448cf86a..6b6847b1fa 100644 --- a/packages/eslint-config-airbnb/test/test-react-order.js +++ b/packages/eslint-config-hudl/test/test-react-order.js @@ -8,7 +8,9 @@ const cli = new CLIEngine({ baseConfig: eslintrc, // This rule fails when executing on text. - rules: { indent: 0 }, + rules: { + indent: 0, + }, }); function lint(text) { From d68c193bed6d91e50923f7ae75c63ddfc9aff885 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Tue, 2 Feb 2016 00:06:04 -0700 Subject: [PATCH 21/71] use simple tests for now --- packages/eslint-config-hudl/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index 77a124346d..ee2bbf7781 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -42,7 +42,7 @@ "hudl-ci": { "buildCommand": null, "lintCommand": "./node_modules/.bin/gulp lint", - "testCommand": "./node_modules/.bin/gulp test" + "testCommand": "npm run tests-only" }, "tasksConfig": { "test": { From 14c4ff8bcc5f857ddcfd9e95c216def50af69434 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Tue, 2 Feb 2016 00:27:17 -0700 Subject: [PATCH 22/71] Add eslint-teamcity reporter --- packages/eslint-config-hudl/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index ee2bbf7781..ccafad08b8 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -61,6 +61,7 @@ "babel-tape-runner": "1.2.0", "eslint": "^1.10.3", "eslint-plugin-react": "^3.12.0", + "eslint-teamcity": "^1.0.0", "fs-extra": "^0.26.5", "gulp": "^3.9.0", "gulp-eslint": "^1.1.1", From 82836228ec5e79d36bd3b1758d0a72484755a3db Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Wed, 3 Feb 2016 16:48:20 -0700 Subject: [PATCH 23/71] Use more appropriate settings for node code --- packages/eslint-config-hudl/.eslintrc | 10 +++++++++- packages/eslint-config-hudl/tasks/.eslintrc | 10 ---------- packages/eslint-config-hudl/tasks/config/index.js | 8 ++++---- packages/eslint-config-hudl/tasks/lint.js | 6 +++--- packages/eslint-config-hudl/tasks/test.js | 14 +++++++------- 5 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 packages/eslint-config-hudl/tasks/.eslintrc diff --git a/packages/eslint-config-hudl/.eslintrc b/packages/eslint-config-hudl/.eslintrc index d811f404b4..f8329cd74e 100644 --- a/packages/eslint-config-hudl/.eslintrc +++ b/packages/eslint-config-hudl/.eslintrc @@ -1,3 +1,11 @@ { - "extends": "./index.js" + "extends": "./legacy.js", + "ecmaFeatures": { + // Recognize `const` keyword. Note that this also enables `let`, even though it's not available + "blockBindings": true + }, + "rules": { + // This is super annoying and won't be relevant with arrow functions + "func-names": 0 + } } diff --git a/packages/eslint-config-hudl/tasks/.eslintrc b/packages/eslint-config-hudl/tasks/.eslintrc deleted file mode 100644 index a2fdaad018..0000000000 --- a/packages/eslint-config-hudl/tasks/.eslintrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../legacy.js", - "rules": { - "func-names": 0 - }, - "env": { - "node": true - }, - "root": true -} diff --git a/packages/eslint-config-hudl/tasks/config/index.js b/packages/eslint-config-hudl/tasks/config/index.js index 8827aa3088..b33c10cd0f 100644 --- a/packages/eslint-config-hudl/tasks/config/index.js +++ b/packages/eslint-config-hudl/tasks/config/index.js @@ -1,13 +1,13 @@ // Pull basic config settings from package.json // Could also check an env variable for override or programmatic creation -var path = require('path'); +const path = require('path'); -var configKey = 'tasksConfig'; +const configKey = 'tasksConfig'; -var packageJson = require(path.resolve('package.json')); +const packageJson = require(path.resolve('package.json')); -var config = packageJson[configKey]; +const config = packageJson[configKey]; if (!config) { throw new Error('Gulp task configuration not found. Looking for `' + configKey + '` property in package.json.'); diff --git a/packages/eslint-config-hudl/tasks/lint.js b/packages/eslint-config-hudl/tasks/lint.js index 6fcd694a6b..c000782eef 100644 --- a/packages/eslint-config-hudl/tasks/lint.js +++ b/packages/eslint-config-hudl/tasks/lint.js @@ -1,6 +1,6 @@ -var gulp = require('gulp'); -var eslint = require('gulp-eslint'); -var gulpIf = require('gulp-if'); +const gulp = require('gulp'); +const eslint = require('gulp-eslint'); +const gulpIf = require('gulp-if'); function isFixed(file) { // Has ESLint fixed the file contents? diff --git a/packages/eslint-config-hudl/tasks/test.js b/packages/eslint-config-hudl/tasks/test.js index 8571a5ecaf..c9d17201c2 100644 --- a/packages/eslint-config-hudl/tasks/test.js +++ b/packages/eslint-config-hudl/tasks/test.js @@ -1,11 +1,11 @@ -var path = require('path'); -var fs = require('fs-extra'); -var gulp = require('gulp'); -var mocha = require('gulp-mocha'); -var istanbul = require('gulp-istanbul'); -var config = require('./config').test; +const path = require('path'); +const fs = require('fs-extra'); +const gulp = require('gulp'); +const mocha = require('gulp-mocha'); +const istanbul = require('gulp-istanbul'); +const config = require('./config').test; -var testCoverageDir = './reports/coverage'; +const testCoverageDir = './reports/coverage'; gulp.task('pre-test', function() { return gulp.src(config.src) From cb512e6b2255abb0d537876d88be55ab2e2d7876 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 00:55:16 -0700 Subject: [PATCH 24/71] Add some comparison generation --- packages/eslint-config-hudl/.eslintrc | 4 +- .../docs/comparisons/with-airbnb-master.md | 413 ++++++++++++++++++ packages/eslint-config-hudl/package.json | 9 +- packages/eslint-config-hudl/tasks/diff.js | 17 + .../tasks/diff/ConfigDiff.js | 170 +++++++ .../tasks/diff/current-config/.eslintrc | 195 +++++++++ .../tasks/diff/diff-template.md | 46 ++ packages/eslint-config-hudl/test/.eslintrc | 2 + 8 files changed, 854 insertions(+), 2 deletions(-) create mode 100644 packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md create mode 100644 packages/eslint-config-hudl/tasks/diff.js create mode 100644 packages/eslint-config-hudl/tasks/diff/ConfigDiff.js create mode 100644 packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc create mode 100644 packages/eslint-config-hudl/tasks/diff/diff-template.md diff --git a/packages/eslint-config-hudl/.eslintrc b/packages/eslint-config-hudl/.eslintrc index f8329cd74e..9c3467c220 100644 --- a/packages/eslint-config-hudl/.eslintrc +++ b/packages/eslint-config-hudl/.eslintrc @@ -6,6 +6,8 @@ }, "rules": { // This is super annoying and won't be relevant with arrow functions - "func-names": 0 + "func-names": 0, + // Suspending this because my esformatter plugin is adding spaces around commented-out parameters + "space-in-parens": 0 } } diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md new file mode 100644 index 0000000000..29ad94cb16 --- /dev/null +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -0,0 +1,413 @@ +# ESLint Config Diff + +Comparison of changes between ours and airbnb's. Rules have been normalized to the array format for consistent diff formatting. + +Base (ours): ----- +Comparison (theirs): ----- + +## Intentional differences +These are differences described in [DIFF FILE](diff-file.json). + +### Env +### Plugins +### Rules + +## Unknown/unmerged differences +These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply +upstream changes that haven't been merged yet. + +### Env +### Plugins +### Rules + + +- + [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) + - [0] +- + [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) + - [2, "never"] +- + [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) + - [2, "as-needed"] +- + [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) + - [0] +- + [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) + - [2, {"before":true,"after":true}] +- + [callback-return](http://eslint.org/docs/rules/callback-return.html) + - [0] +- + [complexity](http://eslint.org/docs/rules/complexity.html) + - [0, 11] +- + [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) + - [2, "never"] +- + [consistent-this](http://eslint.org/docs/rules/consistent-this.html) + - [0] +- + [constructor-super](http://eslint.org/docs/rules/constructor-super.html) + - [0] +- + [dot-location](http://eslint.org/docs/rules/dot-location.html) + - [0] +- + [func-style](http://eslint.org/docs/rules/func-style.html) + - [0] +- + [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) + - [0] +- + [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) + - [0] +- + [id-length](http://eslint.org/docs/rules/id-length.html) + - [0] +- + [id-match](http://eslint.org/docs/rules/id-match.html) + - [0] +- + [indent](http://eslint.org/docs/rules/indent.html) + - [2, 2] + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] +- + [init-declarations](http://eslint.org/docs/rules/init-declarations.html) + - [0] +- + [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) + - [2] + - [2, "prefer-double"] +- + [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) + - [0] +- + [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) + - [0] +- + [max-depth](http://eslint.org/docs/rules/max-depth.html) + - [0, 4] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] +- + [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) + - [0] +- + [max-params](http://eslint.org/docs/rules/max-params.html) + - [0, 3] +- + [max-statements](http://eslint.org/docs/rules/max-statements.html) + - [0, 10] +- + [new-cap](http://eslint.org/docs/rules/new-cap.html) + - [2, {"newIsCap":true,"capIsNew":false}] + - [2, {"newIsCap":true}] +- + [new-parens](http://eslint.org/docs/rules/new-parens.html) + - [0] +- + [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) + - [0] +- + [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) + - [0] +- + [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) + - [0] +- + [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) + - [0] +- + [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) + - [0] +- + [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) + - [2] +- + [no-continue](http://eslint.org/docs/rules/no-continue.html) + - [0] +- + [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) + - [2] +- + [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) + - [2] +- + [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) + - [0] +- + [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) + - [2] +- + [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) + - [2] +- + [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) + - [2] +- + [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) + - [2] + - [0] +- + [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) + - [0] +- + [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) + - [0] +- + [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) + - [0] +- + [no-iterator](http://eslint.org/docs/rules/no-iterator.html) + - [2] +- + [no-label-var](http://eslint.org/docs/rules/no-label-var.html) + - [0] +- + [no-labels](http://eslint.org/docs/rules/no-labels.html) + - [2] +- + [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) + - [0] +- + [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) + - [0, false] +- + [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) + - [2] +- + [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) + - [2] +- + [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) + - [2, {"max":2}] + - [2, {"max":2,"maxEOF":1}] +- + [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) + - [2] +- + [no-new-require](http://eslint.org/docs/rules/no-new-require.html) + - [0] +- + [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) + - [2] + - [2, {"props":true}] +- + [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) + - [0] +- + [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) + - [0] +- + [no-process-env](http://eslint.org/docs/rules/no-process-env.html) + - [0] +- + [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) + - [0] +- + [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) + - [2] +- + [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) + - [0] +- + [no-sync](http://eslint.org/docs/rules/no-sync.html) + - [0] +- + [no-ternary](http://eslint.org/docs/rules/no-ternary.html) + - [0] +- + [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) + - [0] +- + [no-undef](http://eslint.org/docs/rules/no-undef.html) + - [2] +- + [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) + - [0] +- + [no-undefined](http://eslint.org/docs/rules/no-undefined.html) + - [0] +- + [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) + - [0] +- + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] +- + [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) + - [2] +- + [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) + - [0] +- + [no-void](http://eslint.org/docs/rules/no-void.html) + - [0] +- + [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) + - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] +- + [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) + - [2, "always"] +- + [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) + - [2, "always"] +- + [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) + - [0] +- + [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) + - [0] +- + [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) + - [2] +- + [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) + - [0] +- + [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) + - [0] +- + [prefer-template](http://eslint.org/docs/rules/prefer-template.html) + - [2] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "consistent"] + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "consistent"] + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] +- react/display-name + - [0] + - [0, {"acceptTranspilerName":false}] +- react/forbid-prop-types + - [0] + - [0, {"forbid":["any","array","object"]}] +- react/jsx-boolean-value + - [2] + - [2, "never"] +- react/jsx-closing-bracket-location + - [0] + - [2, "line-aligned"] +- react/jsx-closing-bracket-location + - [0] + - [2, "line-aligned"] +- react/jsx-curly-spacing + - [0] + - [0, "never", {"allowMultiline":true}] +- react/jsx-curly-spacing + - [0] + - [0, "never", {"allowMultiline":true}] +- react/jsx-handler-names + - [0] + - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] +- react/jsx-indent-props + - [0] + - [2, 2] +- react/jsx-indent-props + - [0] + - [2, 2] +- react/jsx-max-props-per-line + - [0] + - [0, {"maximum":1}] +- react/jsx-no-bind + - [0] + - [2] +- react/jsx-no-duplicate-props + - [0] + - [0, {"ignoreCase":false}] +- react/jsx-sort-prop-types + - [0] + - [0, {"ignoreCase":false,"callbacksLast":false}] +- react/jsx-sort-props + - [0] + - [0, {"ignoreCase":false,"callbacksLast":false}] +- react/jsx-uses-react + - [2] + - [2, {"pragma":"React"}] +- react/no-deprecated + - [0] + - [1, {"react":"0.14.0"}] +- react/no-deprecated + - [0] + - [1, {"react":"0.14.0"}] +- react/no-did-update-set-state + - [2] + - [2, "allow-in-func"] +- react/no-is-mounted + - [0] + - [2] +- react/no-multi-comp + - [2] + - [2, {"ignoreStateless":true}] +- react/prefer-es6-class + - [0] + - [2, "always"] +- react/prefer-es6-class + - [0] + - [2, "always"] +- react/prop-types + - [2] + - [2, {"ignore":[],"customValidators":[]}] +- react/require-extension + - [0] + - [0, {"extensions":[".jsx"]}] +- react/sort-comp + - [2] + - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] +- react/wrap-multilines + - [2] + - [2, {"declaration":true,"assignment":true,"return":true}] +- + [require-yield](http://eslint.org/docs/rules/require-yield.html) + - [0] +- + [sort-vars](http://eslint.org/docs/rules/sort-vars.html) + - [0] +- + [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) + - [2] + - [2, "always"] +- + [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) + - [2, "never"] + - [2, {"anonymous":"never","named":"never"}] +- + [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) + - [2, "always"] +- + [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) + - [2, "never"] +- + [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) + - [0] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2] + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2] + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] +- + [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) + - [0] +- + [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) + - [2] +- + [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) + - [2, "any"] + - [2, "outside"] +- + [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) + - [0] diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index ccafad08b8..5eed2df4cb 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -59,6 +59,9 @@ }, "devDependencies": { "babel-tape-runner": "1.2.0", + "big-object-diff": "^0.7.0", + "deep-diff": "^0.3.3", + "deep-property": "^1.1.0", "eslint": "^1.10.3", "eslint-plugin-react": "^3.12.0", "eslint-teamcity": "^1.0.0", @@ -68,9 +71,13 @@ "gulp-if": "^2.0.0", "gulp-istanbul": "^0.10.3", "gulp-mocha": "^2.2.0", + "handlebars": "^4.0.5", + "lodash": "^4.2.1", "react": "^0.13.3", + "request-promise": "^2.0.0", "require-dir": "^0.3.0", - "tape": "^4.2.2" + "tape": "^4.2.2", + "tmp": "0.0.28" }, "peerDependencies": { "eslint": ">=1.0.0" diff --git a/packages/eslint-config-hudl/tasks/diff.js b/packages/eslint-config-hudl/tasks/diff.js new file mode 100644 index 0000000000..c791fc63a6 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/diff.js @@ -0,0 +1,17 @@ +const path = require('path'); +const gulp = require('gulp'); +const fs = require('fs-extra'); +const ConfigDiff = require('./diff/ConfigDiff'); + +gulp.task('diff', function() { + return new ConfigDiff() + .compare( + // 'https://raw.githubusercontent.com/hudl/javascript/master/linters/.eslintrc', + require.resolve('./diff/current-config/.eslintrc'), + require.resolve('../index.js')) + .then(function(diff) { + const outputPath = path.resolve('docs/comparisons/with-airbnb-master.md'); + fs.outputFile(outputPath, diff); + console.log('Diff written to ', outputPath); + }); +}); diff --git a/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js b/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js new file mode 100644 index 0000000000..f20a885175 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js @@ -0,0 +1,170 @@ +const path = require('path'); +const request = require('request-promise'); +const fs = require('fs-extra'); +const _ = require('lodash'); +const tmp = require('tmp'); +const Config = require('eslint/lib/config'); +const diff = require('deep-diff').diff; +const Handlebars = require('handlebars'); +const diffTemplatePath = require.resolve('./diff-template.md'); + +function ConfigDiff() { +} + +function normalizeRules(config) { + _.each(config.rules, function(val, key, rules) { + if (_.isNumber(val)) { + rules[key] = [val]; // eslint-disable-line no-param-reassign + } + }); + return config; +} + +function detailedDiff(ourConfig, theirConfig) { + const differences = diff(ourConfig.rules, theirConfig.rules); + const ruleDifferences = differences.map(function(change) { + var valueArrays; + var changeType; + + function diffValueChanges(thisSet, otherSet, flag) { + return thisSet.map(function(value, i) { + const valueInfo = { + rawValue: value, + }; + if (!_.isEqual(value, otherSet[i])) { + valueInfo[flag] = true; + } + return valueInfo; + }); + } + + if (change.kind === 'N' && change.path.length === 1) { + changeType = 'added'; + valueArrays = [ + change.rhs.map(function(value) { + return { + rawValue: value, + added: true, + }; + }), + ]; + } else if (change.kind === 'D' && change.path.length === 1) { + changeType = 'removed'; + valueArrays = [ + change.lhs.map(function(value) { + return { + rawValue: value, + removed: true, + }; + }), + ]; + } else { + changeType = 'edited'; + + const prevValue = ourConfig.rules[change.path[0]]; + const newValue = theirConfig.rules[change.path[0]]; + + valueArrays = [ + diffValueChanges(prevValue, newValue, 'removed'), + diffValueChanges(newValue, prevValue, 'added'), + ]; + } + + // Shape objects for formatting + valueArrays.forEach(function(valueArray) { + valueArray.forEach(function(valueInfo, i) { + // JSON-format values + valueInfo.value = JSON.stringify(valueInfo.rawValue); + + // Add `last` flags for formatting purposes + if (i === valueArray.length - 1) { + valueInfo.last = true; + } + }); + }); + + function getUrl(name) { + if (/\//.test(name)) { + return null; + } + return 'http://eslint.org/docs/rules/' + name + '.html'; + } + + return { + name: change.path[0], + url: getUrl(change.path[0]), + changeType: changeType, + valueArrays: valueArrays, + }; + }); + + const templateData = { + rules: _.sortBy(ruleDifferences, 'name'), + }; + + return Handlebars.compile(fs.readFileSync(diffTemplatePath, 'utf8'))(templateData); +} + +function generateDiff(ours, theirs /* , options*/ ) { + // if (options) { + // // hash + // _.each(options.overwrite, function(val, key) { + // deep.set(theirs.config, key, val); + // }); + // // array + // _.each(options.ignore, function(val) { + // deep.remove(theirs.config, val); + // }); + // } + + [ours.config, theirs.config].forEach(normalizeRules); + return detailedDiff(ours.config, theirs.config); +} + +ConfigDiff.prototype.compare = function(configPath1, configPath2, options) { + const configPaths = [configPath1, configPath2]; + return this._loadConfigs(configPaths) + .then(function(configs) { + return generateDiff({ + path: configPath1, + config: configs[0], + }, { + path: configPath2, + config: configs[1], + }, options); + }); +}; + +ConfigDiff.prototype._loadConfigs = function(configPaths) { + return Promise.all(configPaths.map(function(configPath) { + return this._resolveFilePath(configPath) + .then(function(filePath) { + return this._loadConfig(filePath); + }.bind(this)); + }.bind(this))); +}; + +ConfigDiff.prototype._resolveFilePath = function(configPath) { + if (/^https?:/.test(configPath)) { + return request(configPath) + .then(function(contents) { + const tmpDir = tmp.dirSync({ + unsafeCleanup: true, + }); + const filePath = path.resolve(tmpDir.name, path.basename(configPath) || '.eslintrc'); + fs.outputFileSync(filePath, contents); + + return filePath; + }); + } + return Promise.resolve(configPath); +}; + +ConfigDiff.prototype._loadConfig = function(configFilePath) { + return new Config({ + configFile: configFilePath, + useEslintrc: false, + }).getConfig(); +}; + +module.exports = ConfigDiff; diff --git a/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc b/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc new file mode 100644 index 0000000000..956ac91222 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc @@ -0,0 +1,195 @@ +{ + "parser": "babel-eslint", // https://github.com/babel/babel-eslint + "plugins": [ + "react" // https://github.com/yannickcr/eslint-plugin-react + ], + "env": { // http://eslint.org/docs/user-guide/configuring.html#specifying-environments + "browser": true, // browser global variables + "node": true // Node.js global variables and Node.js-specific rules + }, + "ecmaFeatures": { + "arrowFunctions": true, + "blockBindings": true, + "classes": true, + "defaultParams": true, + "destructuring": true, + "forOf": true, + "generators": false, + "modules": true, + "objectLiteralComputedProperties": true, + "objectLiteralDuplicateProperties": false, + "objectLiteralShorthandMethods": true, + "objectLiteralShorthandProperties": true, + "spread": true, + "superInFunctions": true, + "templateStrings": true, + "jsx": true + }, + "rules": { +/** + * Strict mode + */ + // babel inserts "use strict"; for us + "strict": [2, "never"], // http://eslint.org/docs/rules/strict + +/** + * ES6 + */ + "no-var": 2, // http://eslint.org/docs/rules/no-var + "prefer-const": 2, // http://eslint.org/docs/rules/prefer-const + +/** + * Variables + */ + "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow + "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names + "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars + "vars": "local", + "args": "after-used" + }], + "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define + +/** + * Possible errors + */ + "comma-dangle": [2, "always-multiline"], // http://eslint.org/docs/rules/comma-dangle + "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign + "no-console": 1, // http://eslint.org/docs/rules/no-console + "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger + "no-alert": 1, // http://eslint.org/docs/rules/no-alert + "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition + "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys + "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case + "no-empty": 2, // http://eslint.org/docs/rules/no-empty + "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign + "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast + "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi + "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign + "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations + "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp + "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace + "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls + "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays + "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable + "quote-props": [2, "consistent"],// http://eslint.org/docs/rules/quote-props.html + "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan + "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var + +/** + * Best practices + */ + "max-len": [2, 120, 4], // http://eslint.org/docs/rules/max-len.html + "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return + "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly + "default-case": 2, // http://eslint.org/docs/rules/default-case + "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation + "allowKeywords": true + }], + "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq + "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in + "no-caller": 2, // http://eslint.org/docs/rules/no-caller + "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return + "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null + "no-eval": 2, // http://eslint.org/docs/rules/no-eval + "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native + "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind + "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough + "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal + "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval + "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks + "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func + "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str + "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign + "no-new": 2, // http://eslint.org/docs/rules/no-new + "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func + "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers + "no-octal": 2, // http://eslint.org/docs/rules/no-octal + "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape + "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign + "no-proto": 2, // http://eslint.org/docs/rules/no-proto + "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare + "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign + "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url + "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare + "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences + "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal + "no-with": 2, // http://eslint.org/docs/rules/no-with + "radix": 2, // http://eslint.org/docs/rules/radix + "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top + "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife + "yoda": 2, // http://eslint.org/docs/rules/yoda + +/** + * Style + */ + "indent": [2, 2], // http://eslint.org/docs/rules/indent + "brace-style": [2, // http://eslint.org/docs/rules/brace-style + "1tbs", { + "allowSingleLine": true + }], + "quotes": [ + 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes + ], + "camelcase": [2, { // http://eslint.org/docs/rules/camelcase + "properties": "never" + }], + "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing + "before": false, + "after": true + }], + "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style + "eol-last": 2, // http://eslint.org/docs/rules/eol-last + "func-names": 1, // http://eslint.org/docs/rules/func-names + "jsx-quotes": 2, // http://eslint.org/docs/rules/jsx-quotes + "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing + "beforeColon": false, + "afterColon": true + }], + "new-cap": [2, { // http://eslint.org/docs/rules/new-cap + "newIsCap": true, + "capIsNew": false + }], + "no-extra-parens": [2, "functions"], // http://eslint.org/docs/rules/no-extra-parens.html + "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines + "max": 2 + }], + "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary + "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object + "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func + "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces + "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle + "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var + "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks + "semi": [2, "always"], // http://eslint.org/docs/rules/semi + "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing + "before": false, + "after": true + }], + "space-after-keywords": 2, // http://eslint.org/docs/rules/space-after-keywords + "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks + "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren + "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops + "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case + "spaced-comment": 2, // http://eslint.org/docs/rules/spaced-comment + +/** + * JSX style + */ + "react/display-name": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md + "react/jsx-boolean-value": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md + "react/jsx-no-undef": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md + "react/jsx-sort-props": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md + "react/jsx-sort-prop-types": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-prop-types.md + "react/jsx-uses-react": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md + "react/jsx-uses-vars": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md + "react/no-did-mount-set-state": [2, "allow-in-func"], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md + "react/no-did-update-set-state": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md + "react/no-multi-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md + "react/no-unknown-property": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md + "react/prop-types": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md + "react/react-in-jsx-scope": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md + "react/self-closing-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md + "react/wrap-multilines": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md + "react/sort-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md + } +} diff --git a/packages/eslint-config-hudl/tasks/diff/diff-template.md b/packages/eslint-config-hudl/tasks/diff/diff-template.md new file mode 100644 index 0000000000..fdd6a77d94 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/diff/diff-template.md @@ -0,0 +1,46 @@ +# ESLint Config Diff + +Comparison of changes between ours and airbnb's. Rules have been normalized to the array format for consistent diff formatting. + +Base (ours): ----- +Comparison (theirs): ----- + +## Intentional differences +These are differences described in [DIFF FILE](diff-file.json). + +### Env +### Plugins +### Rules + +## Unknown/unmerged differences +These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply +upstream changes that haven't been merged yet. + +### Env +### Plugins +### Rules + + +{{#each rules}} +- {{#if url}} + [{{name}}]({{url}}) + {{^}} + {{name}} + {{/if}} + {{#each valueArrays}} + - [ + {{~#each this~}} + {{~#if added~}} + {{value}} + {{~^~}} + {{~#if removed~}} + {{value}} + {{~^~}} + {{value}} + {{~/if~}} + {{~/if~}} + {{#unless last}}, {{/unless}} + {{~/each~}} + ] + {{/each}} +{{/each}} diff --git a/packages/eslint-config-hudl/test/.eslintrc b/packages/eslint-config-hudl/test/.eslintrc index 7f79874e41..a9ccc201dd 100644 --- a/packages/eslint-config-hudl/test/.eslintrc +++ b/packages/eslint-config-hudl/test/.eslintrc @@ -1,4 +1,6 @@ { + "root": true, + "extends": '../base.js', "rules": { // disabled because I find it tedious to write tests while following this // rule From 51a94ff9b8ea1f032ccab53086f4798385f82019 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 01:02:07 -0700 Subject: [PATCH 25/71] Use ins/del instead of span --- .../docs/comparisons/with-airbnb-master.md | 288 +++++++++--------- .../tasks/diff/diff-template.md | 4 +- 2 files changed, 146 insertions(+), 146 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index 29ad94cb16..5a9388203b 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -23,391 +23,391 @@ upstream changes that haven't been merged yet. - [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) - - [0] + - [0] - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - - [2, "never"] + - [2, "never"] - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - - [2, "as-needed"] + - [2, "as-needed"] - [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) - - [0] + - [0] - [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) - - [2, {"before":true,"after":true}] + - [2, {"before":true,"after":true}] - [callback-return](http://eslint.org/docs/rules/callback-return.html) - - [0] + - [0] - [complexity](http://eslint.org/docs/rules/complexity.html) - - [0, 11] + - [0, 11] - [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) - - [2, "never"] + - [2, "never"] - [consistent-this](http://eslint.org/docs/rules/consistent-this.html) - - [0] + - [0] - [constructor-super](http://eslint.org/docs/rules/constructor-super.html) - - [0] + - [0] - [dot-location](http://eslint.org/docs/rules/dot-location.html) - - [0] + - [0] - [func-style](http://eslint.org/docs/rules/func-style.html) - - [0] + - [0] - [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) - - [0] + - [0] - [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) - - [0] + - [0] - [id-length](http://eslint.org/docs/rules/id-length.html) - - [0] + - [0] - [id-match](http://eslint.org/docs/rules/id-match.html) - - [0] + - [0] - [indent](http://eslint.org/docs/rules/indent.html) - [2, 2] - - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] - [init-declarations](http://eslint.org/docs/rules/init-declarations.html) - - [0] + - [0] - [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) - [2] - - [2, "prefer-double"] + - [2, "prefer-double"] - [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) - - [0] + - [0] - [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) - - [0] + - [0] - [max-depth](http://eslint.org/docs/rules/max-depth.html) - - [0, 4] + - [0, 4] - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) - - [0] + - [0] - [max-params](http://eslint.org/docs/rules/max-params.html) - - [0, 3] + - [0, 3] - [max-statements](http://eslint.org/docs/rules/max-statements.html) - - [0, 10] + - [0, 10] - [new-cap](http://eslint.org/docs/rules/new-cap.html) - - [2, {"newIsCap":true,"capIsNew":false}] - - [2, {"newIsCap":true}] + - [2, {"newIsCap":true,"capIsNew":false}] + - [2, {"newIsCap":true}] - [new-parens](http://eslint.org/docs/rules/new-parens.html) - - [0] + - [0] - [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) - - [0] + - [0] - [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) - - [0] + - [0] - [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) - - [0] + - [0] - [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) - - [0] + - [0] - [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) - - [0] + - [0] - [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - - [2] + - [2] - [no-continue](http://eslint.org/docs/rules/no-continue.html) - - [0] + - [0] - [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) - - [2] + - [2] - [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) - - [2] + - [2] - [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) - - [0] + - [0] - [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) - - [2] + - [2] - [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) - - [2] + - [2] - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - - [2] + - [2] - [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) - - [2] - - [0] + - [2] + - [0] - [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) - - [0] + - [0] - [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) - - [0] + - [0] - [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) - - [0] + - [0] - [no-iterator](http://eslint.org/docs/rules/no-iterator.html) - - [2] + - [2] - [no-label-var](http://eslint.org/docs/rules/no-label-var.html) - - [0] + - [0] - [no-labels](http://eslint.org/docs/rules/no-labels.html) - - [2] + - [2] - [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) - - [0] + - [0] - [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) - - [0, false] + - [0, false] - [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) - - [2] + - [2] - [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) - - [2] + - [2] - [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) - - [2, {"max":2}] - - [2, {"max":2,"maxEOF":1}] + - [2, {"max":2}] + - [2, {"max":2,"maxEOF":1}] - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) - - [2] + - [2] - [no-new-require](http://eslint.org/docs/rules/no-new-require.html) - - [0] + - [0] - [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) - [2] - - [2, {"props":true}] + - [2, {"props":true}] - [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) - - [0] + - [0] - [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) - - [0] + - [0] - [no-process-env](http://eslint.org/docs/rules/no-process-env.html) - - [0] + - [0] - [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) - - [0] + - [0] - [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) - - [2] + - [2] - [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) - - [0] + - [0] - [no-sync](http://eslint.org/docs/rules/no-sync.html) - - [0] + - [0] - [no-ternary](http://eslint.org/docs/rules/no-ternary.html) - - [0] + - [0] - [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) - - [0] + - [0] - [no-undef](http://eslint.org/docs/rules/no-undef.html) - - [2] + - [2] - [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) - - [0] + - [0] - [no-undefined](http://eslint.org/docs/rules/no-undefined.html) - - [0] + - [0] - [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) - - [0] + - [0] - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] + - [0] - [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) - - [2] + - [2] - [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) - - [0] + - [0] - [no-void](http://eslint.org/docs/rules/no-void.html) - - [0] + - [0] - [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) - - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] + - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] - [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) - - [2, "always"] + - [2, "always"] - [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) - - [2, "always"] + - [2, "always"] - [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) - - [0] + - [0] - [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) - - [0] + - [0] - [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) - - [2] + - [2] - [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) - - [0] + - [0] - [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) - - [0] + - [0] - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - - [2] + - [2] - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "consistent"] - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "consistent"] - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - react/display-name - [0] - - [0, {"acceptTranspilerName":false}] + - [0, {"acceptTranspilerName":false}] - react/forbid-prop-types - [0] - - [0, {"forbid":["any","array","object"]}] + - [0, {"forbid":["any","array","object"]}] - react/jsx-boolean-value - [2] - - [2, "never"] + - [2, "never"] - react/jsx-closing-bracket-location - - [0] - - [2, "line-aligned"] + - [0] + - [2, "line-aligned"] - react/jsx-closing-bracket-location - - [0] - - [2, "line-aligned"] + - [0] + - [2, "line-aligned"] - react/jsx-curly-spacing - [0] - - [0, "never", {"allowMultiline":true}] + - [0, "never", {"allowMultiline":true}] - react/jsx-curly-spacing - [0] - - [0, "never", {"allowMultiline":true}] + - [0, "never", {"allowMultiline":true}] - react/jsx-handler-names - [0] - - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] + - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] - react/jsx-indent-props - - [0] - - [2, 2] + - [0] + - [2, 2] - react/jsx-indent-props - - [0] - - [2, 2] + - [0] + - [2, 2] - react/jsx-max-props-per-line - [0] - - [0, {"maximum":1}] + - [0, {"maximum":1}] - react/jsx-no-bind - - [0] - - [2] + - [0] + - [2] - react/jsx-no-duplicate-props - [0] - - [0, {"ignoreCase":false}] + - [0, {"ignoreCase":false}] - react/jsx-sort-prop-types - [0] - - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0, {"ignoreCase":false,"callbacksLast":false}] - react/jsx-sort-props - [0] - - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0, {"ignoreCase":false,"callbacksLast":false}] - react/jsx-uses-react - [2] - - [2, {"pragma":"React"}] + - [2, {"pragma":"React"}] - react/no-deprecated - - [0] - - [1, {"react":"0.14.0"}] + - [0] + - [1, {"react":"0.14.0"}] - react/no-deprecated - - [0] - - [1, {"react":"0.14.0"}] + - [0] + - [1, {"react":"0.14.0"}] - react/no-did-update-set-state - [2] - - [2, "allow-in-func"] + - [2, "allow-in-func"] - react/no-is-mounted - - [0] - - [2] + - [0] + - [2] - react/no-multi-comp - [2] - - [2, {"ignoreStateless":true}] + - [2, {"ignoreStateless":true}] - react/prefer-es6-class - - [0] - - [2, "always"] + - [0] + - [2, "always"] - react/prefer-es6-class - - [0] - - [2, "always"] + - [0] + - [2, "always"] - react/prop-types - [2] - - [2, {"ignore":[],"customValidators":[]}] + - [2, {"ignore":[],"customValidators":[]}] - react/require-extension - [0] - - [0, {"extensions":[".jsx"]}] + - [0, {"extensions":[".jsx"]}] - react/sort-comp - [2] - - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] + - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] - react/wrap-multilines - [2] - - [2, {"declaration":true,"assignment":true,"return":true}] + - [2, {"declaration":true,"assignment":true,"return":true}] - [require-yield](http://eslint.org/docs/rules/require-yield.html) - - [0] + - [0] - [sort-vars](http://eslint.org/docs/rules/sort-vars.html) - - [0] + - [0] - [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) - [2] - - [2, "always"] + - [2, "always"] - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, "never"] - - [2, {"anonymous":"never","named":"never"}] + - [2, "never"] + - [2, {"anonymous":"never","named":"never"}] - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - - [2, "always"] + - [2, "always"] - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - - [2, "never"] + - [2, "never"] - [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) - - [0] + - [0] - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - [2] - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - [2] - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) - - [0] + - [0] - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - - [2] + - [2] - [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) - - [2, "any"] - - [2, "outside"] + - [2, "any"] + - [2, "outside"] - [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) - - [0] + - [0] diff --git a/packages/eslint-config-hudl/tasks/diff/diff-template.md b/packages/eslint-config-hudl/tasks/diff/diff-template.md index fdd6a77d94..81f1eff030 100644 --- a/packages/eslint-config-hudl/tasks/diff/diff-template.md +++ b/packages/eslint-config-hudl/tasks/diff/diff-template.md @@ -31,10 +31,10 @@ upstream changes that haven't been merged yet. - [ {{~#each this~}} {{~#if added~}} - {{value}} + {{value}} {{~^~}} {{~#if removed~}} - {{value}} + {{value}} {{~^~}} {{value}} {{~/if~}} From b30784f5cb87aeca78c674776df25323b92f1f0d Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 02:06:10 -0700 Subject: [PATCH 26/71] Allow defining known differences --- .../docs/comparisons/with-airbnb-master.md | 143 ++++++++++-------- packages/eslint-config-hudl/tasks/diff.js | 21 ++- .../tasks/diff/ConfigDiff.js | 51 ++++++- .../tasks/diff/diff-section-partial.md | 38 +++++ .../tasks/diff/diff-template.md | 45 ++---- 5 files changed, 195 insertions(+), 103 deletions(-) create mode 100644 packages/eslint-config-hudl/tasks/diff/diff-section-partial.md diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index 5a9388203b..6a171fe124 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -5,28 +5,52 @@ Comparison of changes between ours and airbnb's. Rules have been normalized to t Base (ours): ----- Comparison (theirs): ----- +Changes are presented using the deleted and inserted formatting. + ## Intentional differences These are differences described in [DIFF FILE](diff-file.json). ### Env +_TODO_ + ### Plugins +_TODO_ + ### Rules + +#### Added rules +- + [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) + - [2, "never"] + +#### Removed rules +_None_ + +#### Edited rules +- + [indent](http://eslint.org/docs/rules/indent.html) + - [2, 2] + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] + + ## Unknown/unmerged differences These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply upstream changes that haven't been merged yet. ### Env +_TODO_ + ### Plugins +_TODO_ + ### Rules +#### Added rules - [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) - [0] -- - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - - [2, "never"] - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - [2, "as-needed"] @@ -69,17 +93,9 @@ upstream changes that haven't been merged yet. - [id-match](http://eslint.org/docs/rules/id-match.html) - [0] -- - [indent](http://eslint.org/docs/rules/indent.html) - - [2, 2] - - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] - [init-declarations](http://eslint.org/docs/rules/init-declarations.html) - [0] -- - [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) - - [2] - - [2, "prefer-double"] - [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) - [0] @@ -89,14 +105,6 @@ upstream changes that haven't been merged yet. - [max-depth](http://eslint.org/docs/rules/max-depth.html) - [0, 4] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) - [0] @@ -106,10 +114,6 @@ upstream changes that haven't been merged yet. - [max-statements](http://eslint.org/docs/rules/max-statements.html) - [0, 10] -- - [new-cap](http://eslint.org/docs/rules/new-cap.html) - - [2, {"newIsCap":true,"capIsNew":false}] - - [2, {"newIsCap":true}] - [new-parens](http://eslint.org/docs/rules/new-parens.html) - [0] @@ -152,10 +156,6 @@ upstream changes that haven't been merged yet. - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - [2] -- - [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) - - [2] - - [0] - [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) - [0] @@ -186,20 +186,12 @@ upstream changes that haven't been merged yet. - [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) - [2] -- - [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) - - [2, {"max":2}] - - [2, {"max":2,"maxEOF":1}] - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) - [2] - [no-new-require](http://eslint.org/docs/rules/no-new-require.html) - [0] -- - [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) - - [2] - - [2, {"props":true}] - [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) - [0] @@ -278,6 +270,63 @@ upstream changes that haven't been merged yet. - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - [2] +- + [require-yield](http://eslint.org/docs/rules/require-yield.html) + - [0] +- + [sort-vars](http://eslint.org/docs/rules/sort-vars.html) + - [0] +- + [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) + - [2, "always"] +- + [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) + - [2, "never"] +- + [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) + - [0] +- + [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) + - [0] +- + [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) + - [2] +- + [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) + - [0] + +#### Removed rules +_None_ + +#### Edited rules +- + [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) + - [2] + - [2, "prefer-double"] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 4] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] +- + [new-cap](http://eslint.org/docs/rules/new-cap.html) + - [2, {"newIsCap":true,"capIsNew":false}] + - [2, {"newIsCap":true}] +- + [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) + - [2] + - [0] +- + [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) + - [2, {"max":2}] + - [2, {"max":2,"maxEOF":1}] +- + [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) + - [2] + - [2, {"props":true}] - [quote-props](http://eslint.org/docs/rules/quote-props.html) - [2, "consistent"] @@ -367,12 +416,6 @@ upstream changes that haven't been merged yet. - react/wrap-multilines - [2] - [2, {"declaration":true,"assignment":true,"return":true}] -- - [require-yield](http://eslint.org/docs/rules/require-yield.html) - - [0] -- - [sort-vars](http://eslint.org/docs/rules/sort-vars.html) - - [0] - [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) - [2] @@ -381,15 +424,6 @@ upstream changes that haven't been merged yet. [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - [2, "never"] - [2, {"anonymous":"never","named":"never"}] -- - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - - [2, "always"] -- - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - - [2, "never"] -- - [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) - - [0] - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - [2] @@ -398,16 +432,7 @@ upstream changes that haven't been merged yet. [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - [2] - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] -- - [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) - - [0] -- - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - - [2] - [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) - [2, "any"] - [2, "outside"] -- - [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) - - [0] diff --git a/packages/eslint-config-hudl/tasks/diff.js b/packages/eslint-config-hudl/tasks/diff.js index c791fc63a6..cbd765773d 100644 --- a/packages/eslint-config-hudl/tasks/diff.js +++ b/packages/eslint-config-hudl/tasks/diff.js @@ -1,14 +1,33 @@ +/* eslint quote-props:[2, "consistent"] */ + const path = require('path'); const gulp = require('gulp'); const fs = require('fs-extra'); const ConfigDiff = require('./diff/ConfigDiff'); gulp.task('diff', function() { + const knownRuleDifferences = { + edited: { + // TODO these are just examples + 'indent': [2, 2, { + 'SwitchCase': 1, + 'VariableDeclarator': 1, + }], + }, + added: { + // TODO these are just examples + 'array-bracket-spacing': [2, 'never'], + }, + removed: [ + // 'array-bracket-spacing' + ], + }; return new ConfigDiff() .compare( // 'https://raw.githubusercontent.com/hudl/javascript/master/linters/.eslintrc', require.resolve('./diff/current-config/.eslintrc'), - require.resolve('../index.js')) + require.resolve('../index.js'), + knownRuleDifferences) .then(function(diff) { const outputPath = path.resolve('docs/comparisons/with-airbnb-master.md'); fs.outputFile(outputPath, diff); diff --git a/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js b/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js index f20a885175..be79c0be49 100644 --- a/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js @@ -7,6 +7,7 @@ const Config = require('eslint/lib/config'); const diff = require('deep-diff').diff; const Handlebars = require('handlebars'); const diffTemplatePath = require.resolve('./diff-template.md'); +const diffSectionPartialPath = require.resolve('./diff-section-partial.md'); function ConfigDiff() { } @@ -20,11 +21,12 @@ function normalizeRules(config) { return config; } -function detailedDiff(ourConfig, theirConfig) { +function detailedDiff(ourConfig, theirConfig, options) { const differences = diff(ourConfig.rules, theirConfig.rules); const ruleDifferences = differences.map(function(change) { var valueArrays; var changeType; + var isKnown; function diffValueChanges(thisSet, otherSet, flag) { return thisSet.map(function(value, i) { @@ -40,6 +42,7 @@ function detailedDiff(ourConfig, theirConfig) { if (change.kind === 'N' && change.path.length === 1) { changeType = 'added'; + isKnown = options.added && _.isEqual(options.added[change.path[0]], change.rhs); valueArrays = [ change.rhs.map(function(value) { return { @@ -50,6 +53,7 @@ function detailedDiff(ourConfig, theirConfig) { ]; } else if (change.kind === 'D' && change.path.length === 1) { changeType = 'removed'; + isKnown = options.removed && _.contains(options.removed, change.path[0]); valueArrays = [ change.lhs.map(function(value) { return { @@ -59,11 +63,12 @@ function detailedDiff(ourConfig, theirConfig) { }), ]; } else { - changeType = 'edited'; - const prevValue = ourConfig.rules[change.path[0]]; const newValue = theirConfig.rules[change.path[0]]; + changeType = 'edited'; + isKnown = options.edited && _.isEqual(options.edited[change.path[0]], newValue); + valueArrays = [ diffValueChanges(prevValue, newValue, 'removed'), diffValueChanges(newValue, prevValue, 'added'), @@ -94,18 +99,48 @@ function detailedDiff(ourConfig, theirConfig) { name: change.path[0], url: getUrl(change.path[0]), changeType: changeType, + isKnown: isKnown, valueArrays: valueArrays, }; }); - const templateData = { - rules: _.sortBy(ruleDifferences, 'name'), - }; + function organizeRules(rules) { + const groupedRules = _(rules) + .sortBy('name') + .groupBy('changeType').value(); + + const groupsList = _.map({ + 'Added rules': groupedRules.added || [], + 'Removed rules': groupedRules.removed || [], + 'Edited rules': groupedRules.edited || [], + }, function(val, key) { + return { + groupName: key, + rules: val, + }; + }); + + return { + ruleGroups: groupsList, + }; + } + + function partitionRules(rules) { + const partitioned = _.partition(rules, 'isKnown'); + return { + known: organizeRules(partitioned[0]), + unknown: organizeRules(partitioned[1]), + }; + } + + const templateData = partitionRules(ruleDifferences); + + Handlebars.registerPartial('diffSection', fs.readFileSync(diffSectionPartialPath, 'utf8')); return Handlebars.compile(fs.readFileSync(diffTemplatePath, 'utf8'))(templateData); } -function generateDiff(ours, theirs /* , options*/ ) { +function generateDiff(ours, theirs, options) { // if (options) { // // hash // _.each(options.overwrite, function(val, key) { @@ -118,7 +153,7 @@ function generateDiff(ours, theirs /* , options*/ ) { // } [ours.config, theirs.config].forEach(normalizeRules); - return detailedDiff(ours.config, theirs.config); + return detailedDiff(ours.config, theirs.config, options); } ConfigDiff.prototype.compare = function(configPath1, configPath2, options) { diff --git a/packages/eslint-config-hudl/tasks/diff/diff-section-partial.md b/packages/eslint-config-hudl/tasks/diff/diff-section-partial.md new file mode 100644 index 0000000000..071b913b1f --- /dev/null +++ b/packages/eslint-config-hudl/tasks/diff/diff-section-partial.md @@ -0,0 +1,38 @@ +### Env +_TODO_ + +### Plugins +_TODO_ + +### Rules + +{{#each ruleGroups}} + +#### {{groupName}} +{{#unless rules}} +_None_ +{{/unless}} +{{#each rules}} +- {{#if url}} + [{{name}}]({{url}}) + {{^}} + {{name}} + {{/if}} + {{#each valueArrays}} + - [ + {{~#each this~}} + {{~#if added~}} + {{value}} + {{~^~}} + {{~#if removed~}} + {{value}} + {{~^~}} + {{value}} + {{~/if~}} + {{~/if~}} + {{#unless last}}, {{/unless}} + {{~/each~}} + ] + {{/each}} +{{/each}} +{{/each}} diff --git a/packages/eslint-config-hudl/tasks/diff/diff-template.md b/packages/eslint-config-hudl/tasks/diff/diff-template.md index 81f1eff030..63ac545ebd 100644 --- a/packages/eslint-config-hudl/tasks/diff/diff-template.md +++ b/packages/eslint-config-hudl/tasks/diff/diff-template.md @@ -5,42 +5,17 @@ Comparison of changes between ours and airbnb's. Rules have been normalized to t Base (ours): ----- Comparison (theirs): ----- -## Intentional differences -These are differences described in [DIFF FILE](diff-file.json). +Changes are presented using the deleted and inserted formatting. + +## Known differences +These are intentional differences between our style guide and Airbnb's. This list is generated from explicit data defined within [the diff task](../../tasks/diff.js). + +{{> diffSection known}} -### Env -### Plugins -### Rules ## Unknown/unmerged differences These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply -upstream changes that haven't been merged yet. - -### Env -### Plugins -### Rules - - -{{#each rules}} -- {{#if url}} - [{{name}}]({{url}}) - {{^}} - {{name}} - {{/if}} - {{#each valueArrays}} - - [ - {{~#each this~}} - {{~#if added~}} - {{value}} - {{~^~}} - {{~#if removed~}} - {{value}} - {{~^~}} - {{value}} - {{~/if~}} - {{~/if~}} - {{#unless last}}, {{/unless}} - {{~/each~}} - ] - {{/each}} -{{/each}} +upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of +should be added to the list in [the diff task](../../tasks/diff.js) to remove them from here. + +{{> diffSection unknown}} From fff6ac40ecaf1425f2c9ef803283a86f0404cf29 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 02:06:59 -0700 Subject: [PATCH 27/71] Regenerate diff --- .../docs/comparisons/with-airbnb-master.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index 6a171fe124..ec3cd57824 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -7,8 +7,8 @@ Comparison (theirs): ----- Changes are presented using the deleted and inserted formatting. -## Intentional differences -These are differences described in [DIFF FILE](diff-file.json). +## Known differences +These are intentional differences between our style guide and Airbnb's. This list is generated from explicit data defined within [the diff task](../../tasks/diff.js). ### Env _TODO_ @@ -36,7 +36,8 @@ _None_ ## Unknown/unmerged differences These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply -upstream changes that haven't been merged yet. +upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of +should be added to the list in [the diff task](../../tasks/diff.js) to remove them from here. ### Env _TODO_ From 5ebf341487febc12be72a14728a66d66043fdbbd Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 19:31:08 -0700 Subject: [PATCH 28/71] Flesh out comparison docs and testing around them --- .gitignore | 2 + .../comparisons/before-packaging-refactor.md | 459 ++++++++++++++++++ .../docs/comparisons/with-airbnb-master.md | 419 +--------------- packages/eslint-config-hudl/package.json | 13 +- packages/eslint-config-hudl/tasks/diff.js | 36 -- .../tasks/diff/ConfigDiff.js | 205 -------- .../tasks/diff/current-config/.eslintrc | 195 -------- .../tasks/diff/diff-template.md | 21 - packages/eslint-config-hudl/tasks/docs.js | 7 + .../tasks/docs/diffs/ConfigDiff.js | 327 +++++++++++++ .../tasks/docs/diffs/diff-section-partial.md | 21 + .../tasks/docs/diffs/diff-template.md | 21 + .../tasks/docs/diffs/diffs-to-run.js | 54 +++ .../diffs/rule-item-partial.md} | 17 - .../tasks/docs/writeDocs.js | 30 ++ .../test/__specs__/.eslintrc | 3 + .../test/__specs__/docs-specs.js | 28 ++ .../test/eslint-tests-config.js | 10 + .../test/{ => original}/.eslintrc | 0 .../test/{ => original}/test-base.js | 0 .../test/{ => original}/test-react-order.js | 0 packages/eslint-config-hudl/test/setup.js | 12 + 22 files changed, 1007 insertions(+), 873 deletions(-) create mode 100644 packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md delete mode 100644 packages/eslint-config-hudl/tasks/diff.js delete mode 100644 packages/eslint-config-hudl/tasks/diff/ConfigDiff.js delete mode 100644 packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc delete mode 100644 packages/eslint-config-hudl/tasks/diff/diff-template.md create mode 100644 packages/eslint-config-hudl/tasks/docs.js create mode 100644 packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js create mode 100644 packages/eslint-config-hudl/tasks/docs/diffs/diff-section-partial.md create mode 100644 packages/eslint-config-hudl/tasks/docs/diffs/diff-template.md create mode 100644 packages/eslint-config-hudl/tasks/docs/diffs/diffs-to-run.js rename packages/eslint-config-hudl/tasks/{diff/diff-section-partial.md => docs/diffs/rule-item-partial.md} (70%) create mode 100644 packages/eslint-config-hudl/tasks/docs/writeDocs.js create mode 100644 packages/eslint-config-hudl/test/__specs__/.eslintrc create mode 100644 packages/eslint-config-hudl/test/__specs__/docs-specs.js create mode 100644 packages/eslint-config-hudl/test/eslint-tests-config.js rename packages/eslint-config-hudl/test/{ => original}/.eslintrc (100%) rename packages/eslint-config-hudl/test/{ => original}/test-base.js (100%) rename packages/eslint-config-hudl/test/{ => original}/test-react-order.js (100%) create mode 100644 packages/eslint-config-hudl/test/setup.js diff --git a/.gitignore b/.gitignore index 3c3629e647..b7908d4136 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules + +packages/eslint-config-hudl/reports/ diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md new file mode 100644 index 0000000000..7d712380a0 --- /dev/null +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -0,0 +1,459 @@ +# ESLint Config Diff (vs hudl/javascript before packaging refactor) + +Comparison of changes between ESLint configs. This is the computed result of the source config, including the effects of any extended configs. Changes are presented using the deleted and inserted formatting. + Rules have been normalized to the array format for consistent diff formatting. Non-rule settings are also currently displayed within an array (for rendering simplicity). + +Base (starting point): [../../../index.js](../../../index.js) + +Comparison (additions, removals, edits): [https://github.com/hudl/javascript/blob/53f28eea91be00b7b167deb865ff7468de743b85/linters/.eslintrc](https://github.com/hudl/javascript/blob/53f28eea91be00b7b167deb865ff7468de743b85/linters/.eslintrc) + +## Known differences +These are intentional differences between configs. This list is generated from explicit data defined within [diffs-to-run.js](../../tasks/docs/diffs/diffs-to-run.js). + +### Settings (non-rules) +_None_ + + +### Rules + + +#### Added rules +_None_ + +#### Removed rules +_None_ + +#### Edited rules +_None_ + + +## Unknown/unmerged differences +These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply +upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of +should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-run.js) to remove them from here. + +### Settings (non-rules) + +- parser + - ["babel-eslint"] +- env.amd + - [false] +- env.mocha + - [false] +- env.jasmine + - [false] +- env.es6 + - [false] +- ecmaFeatures.restParams + - [true] + +### Rules + + +#### Added rules +- parser + - ["babel-eslint"] + +#### Removed rules +- + [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) + - [0] +- + [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) + - [2, "never"] +- + [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) + - [2, "as-needed"] +- + [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) + - [0] +- + [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) + - [2, {"before":true,"after":true}] +- + [callback-return](http://eslint.org/docs/rules/callback-return.html) + - [0] +- + [complexity](http://eslint.org/docs/rules/complexity.html) + - [0, 11] +- + [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) + - [2, "never"] +- + [consistent-this](http://eslint.org/docs/rules/consistent-this.html) + - [0] +- + [constructor-super](http://eslint.org/docs/rules/constructor-super.html) + - [0] +- + [dot-location](http://eslint.org/docs/rules/dot-location.html) + - [0] +- ecmaFeatures.restParams + - [true] +- env.amd + - [false] +- env.es6 + - [false] +- env.jasmine + - [false] +- env.mocha + - [false] +- + [func-style](http://eslint.org/docs/rules/func-style.html) + - [0] +- + [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) + - [0] +- + [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) + - [0] +- + [id-length](http://eslint.org/docs/rules/id-length.html) + - [0] +- + [id-match](http://eslint.org/docs/rules/id-match.html) + - [0] +- + [init-declarations](http://eslint.org/docs/rules/init-declarations.html) + - [0] +- + [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) + - [0] +- + [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) + - [0] +- + [max-depth](http://eslint.org/docs/rules/max-depth.html) + - [0, 4] +- + [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) + - [0] +- + [max-params](http://eslint.org/docs/rules/max-params.html) + - [0, 3] +- + [max-statements](http://eslint.org/docs/rules/max-statements.html) + - [0, 10] +- + [new-parens](http://eslint.org/docs/rules/new-parens.html) + - [0] +- + [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) + - [0] +- + [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) + - [0] +- + [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) + - [0] +- + [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) + - [0] +- + [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) + - [0] +- + [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) + - [2] +- + [no-continue](http://eslint.org/docs/rules/no-continue.html) + - [0] +- + [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) + - [2] +- + [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) + - [2] +- + [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) + - [0] +- + [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) + - [2] +- + [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) + - [2] +- + [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) + - [2] +- + [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) + - [0] +- + [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) + - [0] +- + [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) + - [0] +- + [no-iterator](http://eslint.org/docs/rules/no-iterator.html) + - [2] +- + [no-label-var](http://eslint.org/docs/rules/no-label-var.html) + - [0] +- + [no-labels](http://eslint.org/docs/rules/no-labels.html) + - [2] +- + [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) + - [0] +- + [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) + - [0, false] +- + [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) + - [2] +- + [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) + - [2] +- + [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) + - [2] +- + [no-new-require](http://eslint.org/docs/rules/no-new-require.html) + - [0] +- + [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) + - [0] +- + [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) + - [0] +- + [no-process-env](http://eslint.org/docs/rules/no-process-env.html) + - [0] +- + [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) + - [0] +- + [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) + - [2] +- + [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) + - [0] +- + [no-sync](http://eslint.org/docs/rules/no-sync.html) + - [0] +- + [no-ternary](http://eslint.org/docs/rules/no-ternary.html) + - [0] +- + [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) + - [0] +- + [no-undef](http://eslint.org/docs/rules/no-undef.html) + - [2] +- + [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) + - [0] +- + [no-undefined](http://eslint.org/docs/rules/no-undefined.html) + - [0] +- + [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) + - [0] +- + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] +- + [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) + - [2] +- + [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) + - [0] +- + [no-void](http://eslint.org/docs/rules/no-void.html) + - [0] +- + [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) + - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] +- + [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) + - [2, "always"] +- + [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) + - [2, "always"] +- + [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) + - [0] +- + [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) + - [0] +- + [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) + - [2] +- + [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) + - [0] +- + [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) + - [0] +- + [prefer-template](http://eslint.org/docs/rules/prefer-template.html) + - [2] +- + [require-yield](http://eslint.org/docs/rules/require-yield.html) + - [0] +- + [sort-vars](http://eslint.org/docs/rules/sort-vars.html) + - [0] +- + [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) + - [2, "always"] +- + [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) + - [2, "never"] +- + [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) + - [0] +- + [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) + - [0] +- + [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) + - [2] +- + [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) + - [0] + +#### Edited rules +- + [indent](http://eslint.org/docs/rules/indent.html) + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] + - [2, 2] +- + [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) + - [2, "prefer-double"] + - [2] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] +- + [new-cap](http://eslint.org/docs/rules/new-cap.html) + - [2, {"newIsCap":true}] + - [2, {"newIsCap":true,"capIsNew":false}] +- + [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) + - [0] + - [2] +- + [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) + - [2, {"max":2,"maxEOF":1}] + - [2, {"max":2}] +- + [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) + - [2, {"props":true}] + - [2] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] +- react/display-name + - [0, {"acceptTranspilerName":false}] + - [0] +- react/forbid-prop-types + - [0, {"forbid":["any","array","object"]}] + - [0] +- react/jsx-boolean-value + - [2, "never"] + - [2] +- react/jsx-closing-bracket-location + - [2, "line-aligned"] + - [0] +- react/jsx-closing-bracket-location + - [2, "line-aligned"] + - [0] +- react/jsx-curly-spacing + - [0, "never", {"allowMultiline":true}] + - [0] +- react/jsx-curly-spacing + - [0, "never", {"allowMultiline":true}] + - [0] +- react/jsx-handler-names + - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] + - [0] +- react/jsx-indent-props + - [2, 2] + - [0] +- react/jsx-indent-props + - [2, 2] + - [0] +- react/jsx-max-props-per-line + - [0, {"maximum":1}] + - [0] +- react/jsx-no-bind + - [2] + - [0] +- react/jsx-no-duplicate-props + - [0, {"ignoreCase":false}] + - [0] +- react/jsx-sort-prop-types + - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0] +- react/jsx-sort-props + - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0] +- react/jsx-uses-react + - [2, {"pragma":"React"}] + - [2] +- react/no-deprecated + - [1, {"react":"0.14.0"}] + - [0] +- react/no-deprecated + - [1, {"react":"0.14.0"}] + - [0] +- react/no-did-update-set-state + - [2, "allow-in-func"] + - [2] +- react/no-is-mounted + - [2] + - [0] +- react/no-multi-comp + - [2, {"ignoreStateless":true}] + - [2] +- react/prefer-es6-class + - [2, "always"] + - [0] +- react/prefer-es6-class + - [2, "always"] + - [0] +- react/prop-types + - [2, {"ignore":[],"customValidators":[]}] + - [2] +- react/require-extension + - [0, {"extensions":[".jsx"]}] + - [0] +- react/sort-comp + - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] + - [2] +- react/wrap-multilines + - [2, {"declaration":true,"assignment":true,"return":true}] + - [2] +- + [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) + - [2, "always"] + - [2] +- + [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) + - [2, {"anonymous":"never","named":"never"}] + - [2, "never"] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2] +- + [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) + - [2, "outside"] + - [2, "any"] diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index ec3cd57824..b2018df7d4 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -1,439 +1,66 @@ -# ESLint Config Diff +# ESLint Config Diff (vs Airbnb v5.0.0) -Comparison of changes between ours and airbnb's. Rules have been normalized to the array format for consistent diff formatting. +Comparison of changes between ESLint configs. This is the computed result of the source config, including the effects of any extended configs. Changes are presented using the deleted and inserted formatting. + Rules have been normalized to the array format for consistent diff formatting. Non-rule settings are also currently displayed within an array (for rendering simplicity). -Base (ours): ----- -Comparison (theirs): ----- +Base (starting point): [../../../index.js](../../../index.js) -Changes are presented using the deleted and inserted formatting. +Comparison (additions, removals, edits): [https://github.com/airbnb/javascript/tree/eslint-config-airbnb-v5.0.0/packages/eslint-config-airbnb/index.js](https://github.com/airbnb/javascript/tree/eslint-config-airbnb-v5.0.0/packages/eslint-config-airbnb/index.js) ## Known differences -These are intentional differences between our style guide and Airbnb's. This list is generated from explicit data defined within [the diff task](../../tasks/diff.js). +These are intentional differences between configs. This list is generated from explicit data defined within [diffs-to-run.js](../../tasks/docs/diffs/diffs-to-run.js). -### Env -_TODO_ +### Settings (non-rules) +_None_ -### Plugins -_TODO_ ### Rules #### Added rules -- - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - - [2, "never"] +_None_ #### Removed rules _None_ #### Edited rules -- - [indent](http://eslint.org/docs/rules/indent.html) - - [2, 2] - - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] +_None_ ## Unknown/unmerged differences These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of -should be added to the list in [the diff task](../../tasks/diff.js) to remove them from here. +should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-run.js) to remove them from here. -### Env -_TODO_ +### Settings (non-rules) +_None_ -### Plugins -_TODO_ ### Rules #### Added rules - - [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) - - [0] -- - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - - [2, "as-needed"] -- - [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) - - [0] -- - [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) - - [2, {"before":true,"after":true}] -- - [callback-return](http://eslint.org/docs/rules/callback-return.html) - - [0] -- - [complexity](http://eslint.org/docs/rules/complexity.html) - - [0, 11] -- - [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) - - [2, "never"] -- - [consistent-this](http://eslint.org/docs/rules/consistent-this.html) - - [0] -- - [constructor-super](http://eslint.org/docs/rules/constructor-super.html) - - [0] -- - [dot-location](http://eslint.org/docs/rules/dot-location.html) - - [0] -- - [func-style](http://eslint.org/docs/rules/func-style.html) - - [0] -- - [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) - - [0] -- - [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) - - [0] -- - [id-length](http://eslint.org/docs/rules/id-length.html) - - [0] -- - [id-match](http://eslint.org/docs/rules/id-match.html) - - [0] -- - [init-declarations](http://eslint.org/docs/rules/init-declarations.html) - - [0] -- - [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) - - [0] -- - [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) - - [0] -- - [max-depth](http://eslint.org/docs/rules/max-depth.html) - - [0, 4] -- - [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) - - [0] -- - [max-params](http://eslint.org/docs/rules/max-params.html) - - [0, 3] -- - [max-statements](http://eslint.org/docs/rules/max-statements.html) - - [0, 10] -- - [new-parens](http://eslint.org/docs/rules/new-parens.html) - - [0] -- - [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) - - [0] -- - [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) - - [0] -- - [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) - - [0] -- - [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) - - [0] -- - [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) - - [0] -- - [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - - [2] -- - [no-continue](http://eslint.org/docs/rules/no-continue.html) - - [0] -- - [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) - - [2] -- - [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) - - [2] -- - [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) - - [0] -- - [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) - - [2] -- - [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) - - [2] -- - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - - [2] -- - [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) - - [0] -- - [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) - - [0] -- - [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) - - [0] -- - [no-iterator](http://eslint.org/docs/rules/no-iterator.html) - - [2] -- - [no-label-var](http://eslint.org/docs/rules/no-label-var.html) - - [0] -- - [no-labels](http://eslint.org/docs/rules/no-labels.html) - - [2] -- - [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) - - [0] -- - [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) - - [0, false] -- - [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) - - [2] -- - [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) - - [2] -- - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) + [no-case-declarations](http://eslint.org/docs/rules/no-case-declarations.html) - [2] -- - [no-new-require](http://eslint.org/docs/rules/no-new-require.html) - - [0] -- - [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) - - [0] -- - [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) - - [0] -- - [no-process-env](http://eslint.org/docs/rules/no-process-env.html) - - [0] -- - [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) - - [0] -- - [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) - - [2] -- - [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) - - [0] -- - [no-sync](http://eslint.org/docs/rules/no-sync.html) - - [0] -- - [no-ternary](http://eslint.org/docs/rules/no-ternary.html) - - [0] -- - [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) - - [0] -- - [no-undef](http://eslint.org/docs/rules/no-undef.html) - - [2] -- - [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) - - [0] -- - [no-undefined](http://eslint.org/docs/rules/no-undefined.html) - - [0] -- - [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) - - [0] -- - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] -- - [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) - - [2] -- - [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) - - [0] -- - [no-void](http://eslint.org/docs/rules/no-void.html) - - [0] -- - [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) - - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] -- - [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) - - [2, "always"] -- - [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) - - [2, "always"] -- - [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) - - [0] -- - [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) - - [0] -- - [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) - - [2] -- - [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) - - [0] -- - [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) - - [0] -- - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - - [2] -- - [require-yield](http://eslint.org/docs/rules/require-yield.html) - - [0] -- - [sort-vars](http://eslint.org/docs/rules/sort-vars.html) - - [0] -- - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - - [2, "always"] -- - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - - [2, "never"] -- - [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) - - [0] -- - [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) - - [0] -- - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - - [2] -- - [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) - - [0] #### Removed rules _None_ #### Edited rules -- - [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) - - [2] - - [2, "prefer-double"] - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 100, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 4] - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] -- - [new-cap](http://eslint.org/docs/rules/new-cap.html) - - [2, {"newIsCap":true,"capIsNew":false}] - - [2, {"newIsCap":true}] -- - [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) - - [2] - - [0] -- - [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) - - [2, {"max":2}] - - [2, {"max":2,"maxEOF":1}] -- - [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) - - [2] - - [2, {"props":true}] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "consistent"] - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "consistent"] - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] -- react/display-name - - [0] - - [0, {"acceptTranspilerName":false}] -- react/forbid-prop-types - - [0] - - [0, {"forbid":["any","array","object"]}] -- react/jsx-boolean-value - - [2] - - [2, "never"] -- react/jsx-closing-bracket-location - - [0] - - [2, "line-aligned"] -- react/jsx-closing-bracket-location - - [0] - - [2, "line-aligned"] -- react/jsx-curly-spacing - - [0] - - [0, "never", {"allowMultiline":true}] -- react/jsx-curly-spacing - - [0] - - [0, "never", {"allowMultiline":true}] -- react/jsx-handler-names - - [0] - - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] -- react/jsx-indent-props - - [0] - - [2, 2] -- react/jsx-indent-props - - [0] - - [2, 2] -- react/jsx-max-props-per-line - - [0] - - [0, {"maximum":1}] -- react/jsx-no-bind - - [0] - - [2] -- react/jsx-no-duplicate-props - - [0] - - [0, {"ignoreCase":false}] -- react/jsx-sort-prop-types - - [0] - - [0, {"ignoreCase":false,"callbacksLast":false}] -- react/jsx-sort-props - - [0] - - [0, {"ignoreCase":false,"callbacksLast":false}] -- react/jsx-uses-react - - [2] - - [2, {"pragma":"React"}] -- react/no-deprecated - - [0] - - [1, {"react":"0.14.0"}] -- react/no-deprecated - - [0] - - [1, {"react":"0.14.0"}] -- react/no-did-update-set-state - - [2] - - [2, "allow-in-func"] -- react/no-is-mounted - - [0] - - [2] -- react/no-multi-comp - - [2] - - [2, {"ignoreStateless":true}] -- react/prefer-es6-class - - [0] - - [2, "always"] -- react/prefer-es6-class + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - [0] - - [2, "always"] -- react/prop-types - - [2] - - [2, {"ignore":[],"customValidators":[]}] -- react/require-extension - - [0] - - [0, {"extensions":[".jsx"]}] -- react/sort-comp - - [2] - - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] -- react/wrap-multilines - - [2] - - [2, {"declaration":true,"assignment":true,"return":true}] + - [2, {"defaultAssignment":false}] - - [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) - - [2] - - [2, "always"] + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] + - [2, {"defaultAssignment":false}] - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, "never"] - - [2, {"anonymous":"never","named":"never"}] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2] - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2] - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] -- - [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) - - [2, "any"] - - [2, "outside"] + - [2, {"anonymous":"never","named":"never"}] + - [2, {"anonymous":"always","named":"never"}] diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index 5eed2df4cb..b12624cb34 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -4,8 +4,8 @@ "description": "Hudl's ESLint config, following our styleguide", "main": "index.js", "scripts": { - "tests-only": "babel-tape-runner ./test/test-*.js", - "test": "gulp test" + "tests-only": "babel-tape-runner ./test/original/test-*.js", + "test": "gulp test && npm run tests-only" }, "repository": { "type": "git", @@ -42,7 +42,7 @@ "hudl-ci": { "buildCommand": null, "lintCommand": "./node_modules/.bin/gulp lint", - "testCommand": "npm run tests-only" + "testCommand": "npm run test" }, "tasksConfig": { "test": { @@ -60,8 +60,12 @@ "devDependencies": { "babel-tape-runner": "1.2.0", "big-object-diff": "^0.7.0", + "chai": "^3.5.0", + "chai-as-promised": "^5.2.0", + "chalk": "^1.1.1", "deep-diff": "^0.3.3", "deep-property": "^1.1.0", + "dir-compare": "0.0.2", "eslint": "^1.10.3", "eslint-plugin-react": "^3.12.0", "eslint-teamcity": "^1.0.0", @@ -76,6 +80,9 @@ "react": "^0.13.3", "request-promise": "^2.0.0", "require-dir": "^0.3.0", + "shelljs": "^0.5.3", + "sinon": "^1.17.3", + "sinon-chai": "^2.8.0", "tape": "^4.2.2", "tmp": "0.0.28" }, diff --git a/packages/eslint-config-hudl/tasks/diff.js b/packages/eslint-config-hudl/tasks/diff.js deleted file mode 100644 index cbd765773d..0000000000 --- a/packages/eslint-config-hudl/tasks/diff.js +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint quote-props:[2, "consistent"] */ - -const path = require('path'); -const gulp = require('gulp'); -const fs = require('fs-extra'); -const ConfigDiff = require('./diff/ConfigDiff'); - -gulp.task('diff', function() { - const knownRuleDifferences = { - edited: { - // TODO these are just examples - 'indent': [2, 2, { - 'SwitchCase': 1, - 'VariableDeclarator': 1, - }], - }, - added: { - // TODO these are just examples - 'array-bracket-spacing': [2, 'never'], - }, - removed: [ - // 'array-bracket-spacing' - ], - }; - return new ConfigDiff() - .compare( - // 'https://raw.githubusercontent.com/hudl/javascript/master/linters/.eslintrc', - require.resolve('./diff/current-config/.eslintrc'), - require.resolve('../index.js'), - knownRuleDifferences) - .then(function(diff) { - const outputPath = path.resolve('docs/comparisons/with-airbnb-master.md'); - fs.outputFile(outputPath, diff); - console.log('Diff written to ', outputPath); - }); -}); diff --git a/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js b/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js deleted file mode 100644 index be79c0be49..0000000000 --- a/packages/eslint-config-hudl/tasks/diff/ConfigDiff.js +++ /dev/null @@ -1,205 +0,0 @@ -const path = require('path'); -const request = require('request-promise'); -const fs = require('fs-extra'); -const _ = require('lodash'); -const tmp = require('tmp'); -const Config = require('eslint/lib/config'); -const diff = require('deep-diff').diff; -const Handlebars = require('handlebars'); -const diffTemplatePath = require.resolve('./diff-template.md'); -const diffSectionPartialPath = require.resolve('./diff-section-partial.md'); - -function ConfigDiff() { -} - -function normalizeRules(config) { - _.each(config.rules, function(val, key, rules) { - if (_.isNumber(val)) { - rules[key] = [val]; // eslint-disable-line no-param-reassign - } - }); - return config; -} - -function detailedDiff(ourConfig, theirConfig, options) { - const differences = diff(ourConfig.rules, theirConfig.rules); - const ruleDifferences = differences.map(function(change) { - var valueArrays; - var changeType; - var isKnown; - - function diffValueChanges(thisSet, otherSet, flag) { - return thisSet.map(function(value, i) { - const valueInfo = { - rawValue: value, - }; - if (!_.isEqual(value, otherSet[i])) { - valueInfo[flag] = true; - } - return valueInfo; - }); - } - - if (change.kind === 'N' && change.path.length === 1) { - changeType = 'added'; - isKnown = options.added && _.isEqual(options.added[change.path[0]], change.rhs); - valueArrays = [ - change.rhs.map(function(value) { - return { - rawValue: value, - added: true, - }; - }), - ]; - } else if (change.kind === 'D' && change.path.length === 1) { - changeType = 'removed'; - isKnown = options.removed && _.contains(options.removed, change.path[0]); - valueArrays = [ - change.lhs.map(function(value) { - return { - rawValue: value, - removed: true, - }; - }), - ]; - } else { - const prevValue = ourConfig.rules[change.path[0]]; - const newValue = theirConfig.rules[change.path[0]]; - - changeType = 'edited'; - isKnown = options.edited && _.isEqual(options.edited[change.path[0]], newValue); - - valueArrays = [ - diffValueChanges(prevValue, newValue, 'removed'), - diffValueChanges(newValue, prevValue, 'added'), - ]; - } - - // Shape objects for formatting - valueArrays.forEach(function(valueArray) { - valueArray.forEach(function(valueInfo, i) { - // JSON-format values - valueInfo.value = JSON.stringify(valueInfo.rawValue); - - // Add `last` flags for formatting purposes - if (i === valueArray.length - 1) { - valueInfo.last = true; - } - }); - }); - - function getUrl(name) { - if (/\//.test(name)) { - return null; - } - return 'http://eslint.org/docs/rules/' + name + '.html'; - } - - return { - name: change.path[0], - url: getUrl(change.path[0]), - changeType: changeType, - isKnown: isKnown, - valueArrays: valueArrays, - }; - }); - - function organizeRules(rules) { - const groupedRules = _(rules) - .sortBy('name') - .groupBy('changeType').value(); - - const groupsList = _.map({ - 'Added rules': groupedRules.added || [], - 'Removed rules': groupedRules.removed || [], - 'Edited rules': groupedRules.edited || [], - }, function(val, key) { - return { - groupName: key, - rules: val, - }; - }); - - return { - ruleGroups: groupsList, - }; - } - - function partitionRules(rules) { - const partitioned = _.partition(rules, 'isKnown'); - return { - known: organizeRules(partitioned[0]), - unknown: organizeRules(partitioned[1]), - }; - } - - const templateData = partitionRules(ruleDifferences); - - Handlebars.registerPartial('diffSection', fs.readFileSync(diffSectionPartialPath, 'utf8')); - - return Handlebars.compile(fs.readFileSync(diffTemplatePath, 'utf8'))(templateData); -} - -function generateDiff(ours, theirs, options) { - // if (options) { - // // hash - // _.each(options.overwrite, function(val, key) { - // deep.set(theirs.config, key, val); - // }); - // // array - // _.each(options.ignore, function(val) { - // deep.remove(theirs.config, val); - // }); - // } - - [ours.config, theirs.config].forEach(normalizeRules); - return detailedDiff(ours.config, theirs.config, options); -} - -ConfigDiff.prototype.compare = function(configPath1, configPath2, options) { - const configPaths = [configPath1, configPath2]; - return this._loadConfigs(configPaths) - .then(function(configs) { - return generateDiff({ - path: configPath1, - config: configs[0], - }, { - path: configPath2, - config: configs[1], - }, options); - }); -}; - -ConfigDiff.prototype._loadConfigs = function(configPaths) { - return Promise.all(configPaths.map(function(configPath) { - return this._resolveFilePath(configPath) - .then(function(filePath) { - return this._loadConfig(filePath); - }.bind(this)); - }.bind(this))); -}; - -ConfigDiff.prototype._resolveFilePath = function(configPath) { - if (/^https?:/.test(configPath)) { - return request(configPath) - .then(function(contents) { - const tmpDir = tmp.dirSync({ - unsafeCleanup: true, - }); - const filePath = path.resolve(tmpDir.name, path.basename(configPath) || '.eslintrc'); - fs.outputFileSync(filePath, contents); - - return filePath; - }); - } - return Promise.resolve(configPath); -}; - -ConfigDiff.prototype._loadConfig = function(configFilePath) { - return new Config({ - configFile: configFilePath, - useEslintrc: false, - }).getConfig(); -}; - -module.exports = ConfigDiff; diff --git a/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc b/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc deleted file mode 100644 index 956ac91222..0000000000 --- a/packages/eslint-config-hudl/tasks/diff/current-config/.eslintrc +++ /dev/null @@ -1,195 +0,0 @@ -{ - "parser": "babel-eslint", // https://github.com/babel/babel-eslint - "plugins": [ - "react" // https://github.com/yannickcr/eslint-plugin-react - ], - "env": { // http://eslint.org/docs/user-guide/configuring.html#specifying-environments - "browser": true, // browser global variables - "node": true // Node.js global variables and Node.js-specific rules - }, - "ecmaFeatures": { - "arrowFunctions": true, - "blockBindings": true, - "classes": true, - "defaultParams": true, - "destructuring": true, - "forOf": true, - "generators": false, - "modules": true, - "objectLiteralComputedProperties": true, - "objectLiteralDuplicateProperties": false, - "objectLiteralShorthandMethods": true, - "objectLiteralShorthandProperties": true, - "spread": true, - "superInFunctions": true, - "templateStrings": true, - "jsx": true - }, - "rules": { -/** - * Strict mode - */ - // babel inserts "use strict"; for us - "strict": [2, "never"], // http://eslint.org/docs/rules/strict - -/** - * ES6 - */ - "no-var": 2, // http://eslint.org/docs/rules/no-var - "prefer-const": 2, // http://eslint.org/docs/rules/prefer-const - -/** - * Variables - */ - "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow - "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names - "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars - "vars": "local", - "args": "after-used" - }], - "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define - -/** - * Possible errors - */ - "comma-dangle": [2, "always-multiline"], // http://eslint.org/docs/rules/comma-dangle - "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign - "no-console": 1, // http://eslint.org/docs/rules/no-console - "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger - "no-alert": 1, // http://eslint.org/docs/rules/no-alert - "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition - "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys - "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case - "no-empty": 2, // http://eslint.org/docs/rules/no-empty - "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign - "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast - "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi - "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign - "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations - "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp - "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace - "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls - "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays - "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable - "quote-props": [2, "consistent"],// http://eslint.org/docs/rules/quote-props.html - "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan - "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var - -/** - * Best practices - */ - "max-len": [2, 120, 4], // http://eslint.org/docs/rules/max-len.html - "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return - "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly - "default-case": 2, // http://eslint.org/docs/rules/default-case - "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation - "allowKeywords": true - }], - "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq - "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in - "no-caller": 2, // http://eslint.org/docs/rules/no-caller - "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return - "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null - "no-eval": 2, // http://eslint.org/docs/rules/no-eval - "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native - "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind - "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough - "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal - "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval - "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks - "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func - "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str - "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign - "no-new": 2, // http://eslint.org/docs/rules/no-new - "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func - "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers - "no-octal": 2, // http://eslint.org/docs/rules/no-octal - "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape - "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign - "no-proto": 2, // http://eslint.org/docs/rules/no-proto - "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare - "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign - "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url - "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare - "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences - "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal - "no-with": 2, // http://eslint.org/docs/rules/no-with - "radix": 2, // http://eslint.org/docs/rules/radix - "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top - "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife - "yoda": 2, // http://eslint.org/docs/rules/yoda - -/** - * Style - */ - "indent": [2, 2], // http://eslint.org/docs/rules/indent - "brace-style": [2, // http://eslint.org/docs/rules/brace-style - "1tbs", { - "allowSingleLine": true - }], - "quotes": [ - 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes - ], - "camelcase": [2, { // http://eslint.org/docs/rules/camelcase - "properties": "never" - }], - "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing - "before": false, - "after": true - }], - "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style - "eol-last": 2, // http://eslint.org/docs/rules/eol-last - "func-names": 1, // http://eslint.org/docs/rules/func-names - "jsx-quotes": 2, // http://eslint.org/docs/rules/jsx-quotes - "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing - "beforeColon": false, - "afterColon": true - }], - "new-cap": [2, { // http://eslint.org/docs/rules/new-cap - "newIsCap": true, - "capIsNew": false - }], - "no-extra-parens": [2, "functions"], // http://eslint.org/docs/rules/no-extra-parens.html - "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines - "max": 2 - }], - "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary - "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object - "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func - "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces - "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle - "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var - "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks - "semi": [2, "always"], // http://eslint.org/docs/rules/semi - "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing - "before": false, - "after": true - }], - "space-after-keywords": 2, // http://eslint.org/docs/rules/space-after-keywords - "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks - "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren - "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops - "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case - "spaced-comment": 2, // http://eslint.org/docs/rules/spaced-comment - -/** - * JSX style - */ - "react/display-name": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md - "react/jsx-boolean-value": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md - "react/jsx-no-undef": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md - "react/jsx-sort-props": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md - "react/jsx-sort-prop-types": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-prop-types.md - "react/jsx-uses-react": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md - "react/jsx-uses-vars": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md - "react/no-did-mount-set-state": [2, "allow-in-func"], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md - "react/no-did-update-set-state": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md - "react/no-multi-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md - "react/no-unknown-property": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md - "react/prop-types": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md - "react/react-in-jsx-scope": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md - "react/self-closing-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md - "react/wrap-multilines": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md - "react/sort-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md - } -} diff --git a/packages/eslint-config-hudl/tasks/diff/diff-template.md b/packages/eslint-config-hudl/tasks/diff/diff-template.md deleted file mode 100644 index 63ac545ebd..0000000000 --- a/packages/eslint-config-hudl/tasks/diff/diff-template.md +++ /dev/null @@ -1,21 +0,0 @@ -# ESLint Config Diff - -Comparison of changes between ours and airbnb's. Rules have been normalized to the array format for consistent diff formatting. - -Base (ours): ----- -Comparison (theirs): ----- - -Changes are presented using the deleted and inserted formatting. - -## Known differences -These are intentional differences between our style guide and Airbnb's. This list is generated from explicit data defined within [the diff task](../../tasks/diff.js). - -{{> diffSection known}} - - -## Unknown/unmerged differences -These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply -upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of -should be added to the list in [the diff task](../../tasks/diff.js) to remove them from here. - -{{> diffSection unknown}} diff --git a/packages/eslint-config-hudl/tasks/docs.js b/packages/eslint-config-hudl/tasks/docs.js new file mode 100644 index 0000000000..bfee94efd1 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs.js @@ -0,0 +1,7 @@ +const path = require('path') +const gulp = require('gulp'); +const writeDocs = require('./docs/writeDocs') + +gulp.task('docs', function() { + return writeDocs(); +}); diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js new file mode 100644 index 0000000000..961db0b6fe --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -0,0 +1,327 @@ +const path = require('path'); +const request = require('request-promise'); +const fs = require('fs-extra'); +const _ = require('lodash'); +const tmp = require('tmp'); +const Config = require('eslint/lib/config'); +const diff = require('deep-diff').diff; +const deepProperty = require('deep-property'); +const shell = require('shelljs'); +const Handlebars = require('handlebars'); +const diffTemplatePath = require.resolve('./diff-template.md'); +const diffSectionPartialPath = require.resolve('./diff-section-partial.md'); +const ruleItemPartialPath = require.resolve('./rule-item-partial.md'); + +const npmPackageMatch = /^((eslint-config-airbnb)(\/[^@])?)@(\d+\.\d+\.\d+)$/; + +shell.config.silent = true; + +function ConfigDiff() { +} + +function normalizeRules(config) { + _.each(config.rules, function(val, key, rules) { + if (_.isNumber(val)) { + rules[key] = [val]; // eslint-disable-line no-param-reassign + } + }); + return config; +} + +function diffRules(ourConfig, theirConfig, options) { + const ruleOptions = options.rules; + + const ruleDifferences = (diff(ourConfig.rules, theirConfig.rules) || []).map(function(change) { + var valueArrays; + var changeType; + var isKnown; + + function diffValueChanges(thisSet, otherSet, flag) { + return thisSet.map(function(value, i) { + const valueInfo = { + rawValue: value, + }; + if (!_.isEqual(value, otherSet[i])) { + valueInfo[flag] = true; + } + return valueInfo; + }); + } + + if (change.kind === 'N' && change.path.length === 1) { + changeType = 'added'; + isKnown = ruleOptions.added && _.isEqual(ruleOptions.added[change.path[0]], change.rhs); + valueArrays = [ + change.rhs.map(function(value) { + return { + rawValue: value, + added: true, + }; + }), + ]; + } else if (change.kind === 'D' && change.path.length === 1) { + changeType = 'removed'; + isKnown = ruleOptions.removed && _.includes(ruleOptions.removed, change.path[0]); + valueArrays = [ + change.lhs.map(function(value) { + return { + rawValue: value, + removed: true, + }; + }), + ]; + } else { + const prevValue = ourConfig.rules[change.path[0]]; + const newValue = theirConfig.rules[change.path[0]]; + + changeType = 'edited'; + isKnown = ruleOptions.edited && _.isEqual(ruleOptions.edited[change.path[0]], newValue); + + valueArrays = [ + diffValueChanges(prevValue, newValue, 'removed'), + diffValueChanges(newValue, prevValue, 'added'), + ]; + } + + // Shape objects for formatting + valueArrays.forEach(function(valueArray) { + valueArray.forEach(function(valueInfo, i) { + // JSON-format values + valueInfo.value = JSON.stringify(valueInfo.rawValue); // eslint-disable-line no-param-reassign + + // Add `last` flags for formatting purposes + if (i === valueArray.length - 1) { + valueInfo.last = true; // eslint-disable-line no-param-reassign + } + }); + }); + + function getUrl(name) { + if (/\//.test(name)) { + return null; + } + return 'http://eslint.org/docs/rules/' + name + '.html'; + } + + return { + name: change.path[0], + url: getUrl(change.path[0]), + changeType: changeType, + isKnown: isKnown, + valueArrays: valueArrays, + category: 'rule', + }; + }); + + return ruleDifferences; +} + +function diffEverythingElse(ourConfig, theirConfig /* , options */ ) { + function cleanConfig(config) { + const newConfig = _.cloneDeep(config); + // Already diff'd + delete newConfig.rules; + // The effect of extends is present in the other items + delete newConfig.extends; + return newConfig; + } + + return (diff(cleanConfig(ourConfig), cleanConfig(theirConfig)) || []).map(function(change) { + const isKnown = false; + const changeType = { + N: 'added', + D: 'removed', + E: 'edited', + A: 'edited', + }[change.kind]; + + function createValueArray(from, to, prop) { + var value = { + rawValue: deepProperty.get(from, prop), + }; + if (value.rawValue === undefined) { + return null; + } + value.value = JSON.stringify(value.rawValue); + value.last = true; + value[changeType] = true; + return [value]; + } + + const fullProp = change.path.join('.'); + + const valueArrays = _.compact([ + createValueArray(ourConfig, theirConfig, fullProp), + createValueArray(theirConfig, ourConfig, fullProp), + ]); + + return { + name: fullProp, + url: null, + changeType: changeType, + isKnown: isKnown, + valueArrays: valueArrays, + category: 'other', + }; + }); +} + +function detailedDiff(ours, theirs, options) { + const ruleDifferences = diffRules(ours.config, theirs.config, options); + const otherDifferences = diffEverythingElse(ours.config, theirs.config, options); + + function organizePartitions(rules) { + const categories = _.groupBy(rules, 'category'); + + function groupRules() { + const groupedRules = _(rules) + .sortBy('name') + .groupBy('changeType').value(); + + const groupsList = _.map({ + 'Added rules': groupedRules.added || [], + 'Removed rules': groupedRules.removed || [], + 'Edited rules': groupedRules.edited || [], + }, function(val, key) { + return { + groupName: key, + rules: val, + }; + }); + + return groupsList; + } + + return { + ruleGroups: groupRules(categories.rules), + otherItems: categories.other, + }; + } + + function partitionEverything(rules) { + const partitioned = _.partition(rules, 'isKnown'); + return { + known: organizePartitions(partitioned[0]), + unknown: organizePartitions(partitioned[1]), + }; + } + + return partitionEverything(ruleDifferences.concat(otherDifferences)); +} + +function generateDiff(ours, theirs, options) { + [ours.config, theirs.config].forEach(normalizeRules); + return detailedDiff(ours, theirs, options); +} + +ConfigDiff.prototype.writeDiff = function(options) { + return this.compare(options.base, options.comparison, options.knownDifferences) + .then(function(diffData) { + const renderOutputPath = options.renderOutputPath; + const writeOutputPath = options.writeOutputPath; + + function getUrl(configPath) { + const match = npmPackageMatch.exec(configPath); + if (match) { + const packageVersion = match[4]; + const subpath = match[3] || '/index'; + return 'https://github.com/airbnb/javascript/tree/eslint-config-airbnb-v' + + packageVersion + '/packages/eslint-config-airbnb' + subpath + '.js'; + } else if (/^https?:/.test(configPath)) { + return configPath; + } + return path.relative(renderOutputPath, configPath); + } + + const templateData = { + diff: diffData, + base: getUrl(options.base), + comparison: getUrl(options.comparison), + title: options.title, + }; + + Handlebars.registerPartial('diffSection', fs.readFileSync(diffSectionPartialPath, 'utf8')); + Handlebars.registerPartial('ruleItem', fs.readFileSync(ruleItemPartialPath, 'utf8')); + + fs.outputFileSync(writeOutputPath, Handlebars.compile(fs.readFileSync(diffTemplatePath, 'utf8'))(templateData)); + + return 'Diff written to ' + writeOutputPath; + }); +}; + +ConfigDiff.prototype.compare = function(configPath1, configPath2, options) { + const configPaths = [configPath1, configPath2]; + return this._loadConfigs(configPaths) + .then(function(configs) { + return generateDiff({ + path: configPath1, + config: configs[0], + }, { + path: configPath2, + config: configs[1], + }, options); + }); +}; + +ConfigDiff.prototype._loadConfigs = function(configPaths) { + return Promise.all(configPaths.map(function(configPath) { + return this._resolveFilePath(configPath) + .then(function(filePath) { + return this._loadConfig(filePath); + }.bind(this)); + }.bind(this))); +}; + +ConfigDiff.prototype._resolveFilePath = function(configPath) { + var url; + if (/^https?:/.test(configPath)) { + url = configPath; + if (/^https:\/\/github.com/.test(configPath)) { + url = configPath + .replace(/https:\/\/github.com/, 'https://raw.githubusercontent.com') + .replace('/blob/', '/'); + } + return request(url) + .then(function(contents) { + const tmpDir = tmp.dirSync({ + unsafeCleanup: true, + }); + const filePath = path.resolve(tmpDir.name, path.basename(configPath) || '.eslintrc'); + fs.outputFileSync(filePath, contents); + + return filePath; + }); + } else if (npmPackageMatch.test(configPath)) { + const match = npmPackageMatch.exec(configPath); + + const tmpDir = tmp.dirSync({ + unsafeCleanup: true, + }); + + const packageNameWithPath = match[1]; + const packageName = match[2]; + const packageVersion = match[4]; + + shell.pushd(tmpDir.name); + const result = shell.exec('npm i ' + packageName + '@' + packageVersion); + if (result.code !== 0) { + return Promise.reject(new Error('Error installing config package: ' + result.output)); + } + + const filePath = shell.exec('node -e "console.log(require.resolve(\'' + + packageNameWithPath + '\'))"').output.trim(); + shell.popd(); + + return Promise.resolve(filePath); + } + return Promise.resolve(configPath); +}; + +ConfigDiff.prototype._loadConfig = function(configFilePath) { + return new Config({ + configFile: configFilePath, + useEslintrc: false, + }).getConfig(); +}; + +module.exports = ConfigDiff; diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/diff-section-partial.md b/packages/eslint-config-hudl/tasks/docs/diffs/diff-section-partial.md new file mode 100644 index 0000000000..6b7d549679 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs/diffs/diff-section-partial.md @@ -0,0 +1,21 @@ +### Settings (non-rules) +{{#unless otherItems}} +_None_ +{{/unless}} + +{{#each otherItems}} +{{> ruleItem this}} +{{/each}} + +### Rules + +{{#each ruleGroups}} + +#### {{groupName}} +{{#unless rules}} +_None_ +{{/unless}} +{{#each rules}} +{{> ruleItem this}} +{{/each}} +{{/each}} diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/diff-template.md b/packages/eslint-config-hudl/tasks/docs/diffs/diff-template.md new file mode 100644 index 0000000000..9472d51cb0 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs/diffs/diff-template.md @@ -0,0 +1,21 @@ +# ESLint Config Diff ({{title}}) + +Comparison of changes between ESLint configs. This is the computed result of the source config, including the effects of any extended configs. Changes are presented using the deleted and inserted formatting. + Rules have been normalized to the array format for consistent diff formatting. Non-rule settings are also currently displayed within an array (for rendering simplicity). + +Base (starting point): [{{base}}]({{base}}) + +Comparison (additions, removals, edits): [{{comparison}}]({{comparison}}) + +## Known differences +These are intentional differences between configs. This list is generated from explicit data defined within [diffs-to-run.js](../../tasks/docs/diffs/diffs-to-run.js). + +{{> diffSection diff.known}} + + +## Unknown/unmerged differences +These are differences that haven't been previously acknowledged. They may be changes we aren't aware of or simply +upstream changes that haven't been merged yet. Any differences listed here that we _are_ aware of +should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-run.js) to remove them from here. + +{{> diffSection diff.unknown}} diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/diffs-to-run.js b/packages/eslint-config-hudl/tasks/docs/diffs/diffs-to-run.js new file mode 100644 index 0000000000..5f35b0c758 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs/diffs/diffs-to-run.js @@ -0,0 +1,54 @@ +module.exports = [ + { + // 'https://raw.githubusercontent.com/hudl/javascript/master/linters/.eslintrc', + + title: 'vs Airbnb v5.0.0', + outputName: 'with-airbnb-master', + base: require.resolve('../../../index.js'), + comparison: 'eslint-config-airbnb@5.0.0', + knownDifferences: { + // Known rule differences + rules: { + edited: { + // TODO these are just examples + // 'indent': [2, 2, { + // 'SwitchCase': 1, + // 'VariableDeclarator': 1, + // }], + }, + added: { + // TODO these are just examples + // 'array-bracket-spacing': [2, 'never'], + }, + removed: [ + // 'array-bracket-spacing' + ], + }, + }, + }, + { + title: 'vs hudl/javascript before packaging refactor', + outputName: 'before-packaging-refactor', + base: require.resolve('../../../index.js'), + comparison: 'https://github.com/hudl/javascript/blob/53f28eea91be00b7b167deb865ff7468de743b85/linters/.eslintrc', + knownDifferences: { + // Known rule differences + rules: { + edited: { + // TODO these are just examples + // 'indent': [2, 2, { + // 'SwitchCase': 1, + // 'VariableDeclarator': 1, + // }], + }, + added: { + // TODO these are just examples + // 'array-bracket-spacing': [2, 'never'], + }, + removed: [ + // 'array-bracket-spacing' + ], + }, + }, + }, +]; diff --git a/packages/eslint-config-hudl/tasks/diff/diff-section-partial.md b/packages/eslint-config-hudl/tasks/docs/diffs/rule-item-partial.md similarity index 70% rename from packages/eslint-config-hudl/tasks/diff/diff-section-partial.md rename to packages/eslint-config-hudl/tasks/docs/diffs/rule-item-partial.md index 071b913b1f..ca8bb666d7 100644 --- a/packages/eslint-config-hudl/tasks/diff/diff-section-partial.md +++ b/packages/eslint-config-hudl/tasks/docs/diffs/rule-item-partial.md @@ -1,18 +1,3 @@ -### Env -_TODO_ - -### Plugins -_TODO_ - -### Rules - -{{#each ruleGroups}} - -#### {{groupName}} -{{#unless rules}} -_None_ -{{/unless}} -{{#each rules}} - {{#if url}} [{{name}}]({{url}}) {{^}} @@ -34,5 +19,3 @@ _None_ {{~/each~}} ] {{/each}} -{{/each}} -{{/each}} diff --git a/packages/eslint-config-hudl/tasks/docs/writeDocs.js b/packages/eslint-config-hudl/tasks/docs/writeDocs.js new file mode 100644 index 0000000000..fcba1d5b62 --- /dev/null +++ b/packages/eslint-config-hudl/tasks/docs/writeDocs.js @@ -0,0 +1,30 @@ +/* eslint no-param-reassign:[2, {"props":false}] */ + +const path = require('path'); +const fs = require('fs-extra'); +const ConfigDiff = require('./diffs/ConfigDiff'); +const diffsToRun = require('./diffs/diffs-to-run'); + + +function writeDocs(testOutputDir, clearDirectory) { + const defaultOutputDir = path.resolve('./docs'); + const renderOutputDir = path.resolve(defaultOutputDir, 'comparisons'); + const writeOutputDir = path.resolve(testOutputDir || defaultOutputDir, 'comparisons'); + + if (clearDirectory !== false) { + fs.removeSync(writeOutputDir); + } + + return Promise.all(diffsToRun.map(function(diffOptions) { + const outputFilename = diffOptions.outputName + '.md'; + diffOptions.renderOutputPath = path.resolve(renderOutputDir, outputFilename); + diffOptions.writeOutputPath = path.resolve(writeOutputDir, outputFilename); + return new ConfigDiff() + .writeDiff(diffOptions) + .then(function(message) { + console.log(message); // eslint-disable-line no-console + }); + })); +} + +module.exports = writeDocs; diff --git a/packages/eslint-config-hudl/test/__specs__/.eslintrc b/packages/eslint-config-hudl/test/__specs__/.eslintrc new file mode 100644 index 0000000000..2bc0213fa4 --- /dev/null +++ b/packages/eslint-config-hudl/test/__specs__/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": '../eslint-tests-config.js' +} diff --git a/packages/eslint-config-hudl/test/__specs__/docs-specs.js b/packages/eslint-config-hudl/test/__specs__/docs-specs.js new file mode 100644 index 0000000000..b6fedd0aa9 --- /dev/null +++ b/packages/eslint-config-hudl/test/__specs__/docs-specs.js @@ -0,0 +1,28 @@ +const path = require('path'); +const chalk = require('chalk'); +const tmp = require('tmp'); +const dircompare = require('dir-compare'); +const writeDocs = require('../../tasks/docs/writeDocs'); + +describe('docs', function() { + it('are up-to-date (slow)', function() { + this.timeout(20 * 1000); + const tmpDir = tmp.dirSync({ + unsafeCleanup: true, + }); + + const writeAndCompare = writeDocs(tmpDir.name, false) + .then(function() { + const results = dircompare.compareSync(path.resolve('./docs'), tmpDir.name, { + compareContent: true, + }); + + tmpDir.removeCallback(); + + return results; + }); + + return expect(writeAndCompare).to.eventually.have + .property('same', true, 'Docs need regenerated by running ' + chalk.cyan('gulp docs') + '.'); + }); +}); diff --git a/packages/eslint-config-hudl/test/eslint-tests-config.js b/packages/eslint-config-hudl/test/eslint-tests-config.js new file mode 100644 index 0000000000..662646488b --- /dev/null +++ b/packages/eslint-config-hudl/test/eslint-tests-config.js @@ -0,0 +1,10 @@ +// eslint config to extend for spec directories +module.exports = { + env: { + mocha: true, + }, + globals: { + expect: false, + sinon: false, + }, +}; diff --git a/packages/eslint-config-hudl/test/.eslintrc b/packages/eslint-config-hudl/test/original/.eslintrc similarity index 100% rename from packages/eslint-config-hudl/test/.eslintrc rename to packages/eslint-config-hudl/test/original/.eslintrc diff --git a/packages/eslint-config-hudl/test/test-base.js b/packages/eslint-config-hudl/test/original/test-base.js similarity index 100% rename from packages/eslint-config-hudl/test/test-base.js rename to packages/eslint-config-hudl/test/original/test-base.js diff --git a/packages/eslint-config-hudl/test/test-react-order.js b/packages/eslint-config-hudl/test/original/test-react-order.js similarity index 100% rename from packages/eslint-config-hudl/test/test-react-order.js rename to packages/eslint-config-hudl/test/original/test-react-order.js diff --git a/packages/eslint-config-hudl/test/setup.js b/packages/eslint-config-hudl/test/setup.js new file mode 100644 index 0000000000..17ff29a195 --- /dev/null +++ b/packages/eslint-config-hudl/test/setup.js @@ -0,0 +1,12 @@ +// This is required before every test to remove boilerplate includes. + +const chai = require('chai'); +const sinon = require('sinon'); + +// Add chai plugins +chai.use(require('sinon-chai')); +chai.use(require('chai-as-promised')); +// chai.use(require('./plugins/shelljs-exec')); + +global.expect = chai.expect; +global.sinon = sinon; From 9f8ea57b74aa7e64e0a6f573b61dd7b8f3ac5150 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 19:34:43 -0700 Subject: [PATCH 29/71] Fix relative paths --- .../docs/comparisons/before-packaging-refactor.md | 2 +- .../eslint-config-hudl/docs/comparisons/with-airbnb-master.md | 2 +- packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index 7d712380a0..0f9e063b33 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -3,7 +3,7 @@ Comparison of changes between ESLint configs. This is the computed result of the source config, including the effects of any extended configs. Changes are presented using the deleted and inserted formatting. Rules have been normalized to the array format for consistent diff formatting. Non-rule settings are also currently displayed within an array (for rendering simplicity). -Base (starting point): [../../../index.js](../../../index.js) +Base (starting point): [../../index.js](../../index.js) Comparison (additions, removals, edits): [https://github.com/hudl/javascript/blob/53f28eea91be00b7b167deb865ff7468de743b85/linters/.eslintrc](https://github.com/hudl/javascript/blob/53f28eea91be00b7b167deb865ff7468de743b85/linters/.eslintrc) diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index b2018df7d4..b1c6c43197 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -3,7 +3,7 @@ Comparison of changes between ESLint configs. This is the computed result of the source config, including the effects of any extended configs. Changes are presented using the deleted and inserted formatting. Rules have been normalized to the array format for consistent diff formatting. Non-rule settings are also currently displayed within an array (for rendering simplicity). -Base (starting point): [../../../index.js](../../../index.js) +Base (starting point): [../../index.js](../../index.js) Comparison (additions, removals, edits): [https://github.com/airbnb/javascript/tree/eslint-config-airbnb-v5.0.0/packages/eslint-config-airbnb/index.js](https://github.com/airbnb/javascript/tree/eslint-config-airbnb-v5.0.0/packages/eslint-config-airbnb/index.js) diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index 961db0b6fe..37b1d2acae 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -230,7 +230,7 @@ ConfigDiff.prototype.writeDiff = function(options) { } else if (/^https?:/.test(configPath)) { return configPath; } - return path.relative(renderOutputPath, configPath); + return path.relative(path.dirname(renderOutputPath), configPath); } const templateData = { From 953c43f77e456fbb437c8147693ac0b46057b2e1 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 19:44:23 -0700 Subject: [PATCH 30/71] Update Readme and point to comparison docs --- packages/eslint-config-hudl/README.md | 27 ++++++++++++------------ packages/eslint-config-hudl/package.json | 5 +++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/eslint-config-hudl/README.md b/packages/eslint-config-hudl/README.md index 26c795f3f8..33a01b22bb 100644 --- a/packages/eslint-config-hudl/README.md +++ b/packages/eslint-config-hudl/README.md @@ -1,36 +1,37 @@ -# eslint-config-airbnb +# eslint-config-hudl -[![npm version](https://badge.fury.io/js/eslint-config-airbnb.svg)](http://badge.fury.io/js/eslint-config-airbnb) +This package provides Hudl's .eslintrc as an extensible shared config. -This package provides Airbnb's .eslintrc as an extensible shared config. +**Note:** This is forked from Airbnb's `eslint-config-airbnb` package. To see how Hudl's config compares to +the Airbnb config, take a look at the [comparison docs](docs/comparisons/). ## Usage We export three ESLint configurations for your usage. -### eslint-config-airbnb +### eslint-config-hudl Our default export contains all of our ESLint rules, including EcmaScript 6+ and React. It requires `eslint` and `eslint-plugin-react`. -1. `npm install --save-dev eslint-config-airbnb eslint-plugin-react eslint` -2. add `"extends": "airbnb"` to your .eslintrc +1. `npm install --save-dev eslint-config-hudl eslint-plugin-react eslint --registry=http://npm.thorhudl.com` +2. add `"extends": "hudl"` to your .eslintrc -### eslint-config-airbnb/base +### eslint-config-hudl/base Lints ES6+ but does not lint React. Requires `eslint`. -1. `npm install --save-dev eslint-config-airbnb eslint` -2. add `"extends": "airbnb/base"` to your .eslintrc +1. `npm install --save-dev eslint-config-hudl eslint --registry=http://npm.thorhudl.com` +2. add `"extends": "hudl/base"` to your .eslintrc -### eslint-config-airbnb/legacy +### eslint-config-hudl/legacy Lints ES5 and below. Only requires `eslint`. -1. `npm install --save-dev eslint-config-airbnb eslint` -2. add `"extends": "airbnb/legacy"` to your .eslintrc +1. `npm install --save-dev eslint-config-hudl eslint --registry=http://npm.thorhudl.com` +2. add `"extends": "hudl/legacy"` to your .eslintrc -See [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript) and +See [Hudl's Javascript styleguide](https://github.com/hudl/javascript) and the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information. diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index b12624cb34..ae733a6e89 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "tests-only": "babel-tape-runner ./test/original/test-*.js", - "test": "gulp test && npm run tests-only" + "test": "gulp test && npm run tests-only", + "lint": "gulp lint" }, "repository": { "type": "git", @@ -35,7 +36,7 @@ "bugs": { "url": "https://github.com/hudl/javascript/issues" }, - "homepage": "https://github.com/hudl/javascript", + "homepage": "https://github.com/hudl/javascript/packages/eslint-config-hudl", "publishConfig": { "registry": "http://npm.thorhudl.com" }, From e2d8d29fb5dfdf67af3cde9d7302bab1211b7772 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 19:51:42 -0700 Subject: [PATCH 31/71] Fix rule grouping --- .../comparisons/before-packaging-refactor.md | 405 +----------------- .../docs/comparisons/with-airbnb-master.md | 21 +- .../tasks/docs/diffs/ConfigDiff.js | 6 +- 3 files changed, 8 insertions(+), 424 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index 0f9e063b33..0ad68cc6d3 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -51,409 +51,10 @@ should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-r #### Added rules -- parser - - ["babel-eslint"] +_None_ #### Removed rules -- - [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) - - [0] -- - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - - [2, "never"] -- - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - - [2, "as-needed"] -- - [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) - - [0] -- - [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) - - [2, {"before":true,"after":true}] -- - [callback-return](http://eslint.org/docs/rules/callback-return.html) - - [0] -- - [complexity](http://eslint.org/docs/rules/complexity.html) - - [0, 11] -- - [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) - - [2, "never"] -- - [consistent-this](http://eslint.org/docs/rules/consistent-this.html) - - [0] -- - [constructor-super](http://eslint.org/docs/rules/constructor-super.html) - - [0] -- - [dot-location](http://eslint.org/docs/rules/dot-location.html) - - [0] -- ecmaFeatures.restParams - - [true] -- env.amd - - [false] -- env.es6 - - [false] -- env.jasmine - - [false] -- env.mocha - - [false] -- - [func-style](http://eslint.org/docs/rules/func-style.html) - - [0] -- - [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) - - [0] -- - [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) - - [0] -- - [id-length](http://eslint.org/docs/rules/id-length.html) - - [0] -- - [id-match](http://eslint.org/docs/rules/id-match.html) - - [0] -- - [init-declarations](http://eslint.org/docs/rules/init-declarations.html) - - [0] -- - [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) - - [0] -- - [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) - - [0] -- - [max-depth](http://eslint.org/docs/rules/max-depth.html) - - [0, 4] -- - [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) - - [0] -- - [max-params](http://eslint.org/docs/rules/max-params.html) - - [0, 3] -- - [max-statements](http://eslint.org/docs/rules/max-statements.html) - - [0, 10] -- - [new-parens](http://eslint.org/docs/rules/new-parens.html) - - [0] -- - [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) - - [0] -- - [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) - - [0] -- - [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) - - [0] -- - [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) - - [0] -- - [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) - - [0] -- - [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - - [2] -- - [no-continue](http://eslint.org/docs/rules/no-continue.html) - - [0] -- - [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) - - [2] -- - [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) - - [2] -- - [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) - - [0] -- - [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) - - [2] -- - [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) - - [2] -- - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - - [2] -- - [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) - - [0] -- - [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) - - [0] -- - [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) - - [0] -- - [no-iterator](http://eslint.org/docs/rules/no-iterator.html) - - [2] -- - [no-label-var](http://eslint.org/docs/rules/no-label-var.html) - - [0] -- - [no-labels](http://eslint.org/docs/rules/no-labels.html) - - [2] -- - [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) - - [0] -- - [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) - - [0, false] -- - [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) - - [2] -- - [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) - - [2] -- - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) - - [2] -- - [no-new-require](http://eslint.org/docs/rules/no-new-require.html) - - [0] -- - [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) - - [0] -- - [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) - - [0] -- - [no-process-env](http://eslint.org/docs/rules/no-process-env.html) - - [0] -- - [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) - - [0] -- - [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) - - [2] -- - [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) - - [0] -- - [no-sync](http://eslint.org/docs/rules/no-sync.html) - - [0] -- - [no-ternary](http://eslint.org/docs/rules/no-ternary.html) - - [0] -- - [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) - - [0] -- - [no-undef](http://eslint.org/docs/rules/no-undef.html) - - [2] -- - [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) - - [0] -- - [no-undefined](http://eslint.org/docs/rules/no-undefined.html) - - [0] -- - [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) - - [0] -- - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] -- - [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) - - [2] -- - [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) - - [0] -- - [no-void](http://eslint.org/docs/rules/no-void.html) - - [0] -- - [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) - - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] -- - [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) - - [2, "always"] -- - [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) - - [2, "always"] -- - [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) - - [0] -- - [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) - - [0] -- - [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) - - [2] -- - [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) - - [0] -- - [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) - - [0] -- - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - - [2] -- - [require-yield](http://eslint.org/docs/rules/require-yield.html) - - [0] -- - [sort-vars](http://eslint.org/docs/rules/sort-vars.html) - - [0] -- - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - - [2, "always"] -- - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - - [2, "never"] -- - [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) - - [0] -- - [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) - - [0] -- - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - - [2] -- - [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) - - [0] +_None_ #### Edited rules -- - [indent](http://eslint.org/docs/rules/indent.html) - - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] - - [2, 2] -- - [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) - - [2, "prefer-double"] - - [2] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 120, 4] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 120, 4] -- - [new-cap](http://eslint.org/docs/rules/new-cap.html) - - [2, {"newIsCap":true}] - - [2, {"newIsCap":true,"capIsNew":false}] -- - [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) - - [0] - - [2] -- - [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) - - [2, {"max":2,"maxEOF":1}] - - [2, {"max":2}] -- - [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) - - [2, {"props":true}] - - [2] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - - [2, "consistent"] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - - [2, "consistent"] -- react/display-name - - [0, {"acceptTranspilerName":false}] - - [0] -- react/forbid-prop-types - - [0, {"forbid":["any","array","object"]}] - - [0] -- react/jsx-boolean-value - - [2, "never"] - - [2] -- react/jsx-closing-bracket-location - - [2, "line-aligned"] - - [0] -- react/jsx-closing-bracket-location - - [2, "line-aligned"] - - [0] -- react/jsx-curly-spacing - - [0, "never", {"allowMultiline":true}] - - [0] -- react/jsx-curly-spacing - - [0, "never", {"allowMultiline":true}] - - [0] -- react/jsx-handler-names - - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] - - [0] -- react/jsx-indent-props - - [2, 2] - - [0] -- react/jsx-indent-props - - [2, 2] - - [0] -- react/jsx-max-props-per-line - - [0, {"maximum":1}] - - [0] -- react/jsx-no-bind - - [2] - - [0] -- react/jsx-no-duplicate-props - - [0, {"ignoreCase":false}] - - [0] -- react/jsx-sort-prop-types - - [0, {"ignoreCase":false,"callbacksLast":false}] - - [0] -- react/jsx-sort-props - - [0, {"ignoreCase":false,"callbacksLast":false}] - - [0] -- react/jsx-uses-react - - [2, {"pragma":"React"}] - - [2] -- react/no-deprecated - - [1, {"react":"0.14.0"}] - - [0] -- react/no-deprecated - - [1, {"react":"0.14.0"}] - - [0] -- react/no-did-update-set-state - - [2, "allow-in-func"] - - [2] -- react/no-is-mounted - - [2] - - [0] -- react/no-multi-comp - - [2, {"ignoreStateless":true}] - - [2] -- react/prefer-es6-class - - [2, "always"] - - [0] -- react/prefer-es6-class - - [2, "always"] - - [0] -- react/prop-types - - [2, {"ignore":[],"customValidators":[]}] - - [2] -- react/require-extension - - [0, {"extensions":[".jsx"]}] - - [0] -- react/sort-comp - - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] - - [2] -- react/wrap-multilines - - [2, {"declaration":true,"assignment":true,"return":true}] - - [2] -- - [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) - - [2, "always"] - - [2] -- - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, {"anonymous":"never","named":"never"}] - - [2, "never"] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - - [2] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - - [2] -- - [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) - - [2, "outside"] - - [2, "any"] +_None_ diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index b1c6c43197..43cb9ca2a2 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -40,27 +40,10 @@ _None_ #### Added rules -- - [no-case-declarations](http://eslint.org/docs/rules/no-case-declarations.html) - - [2] +_None_ #### Removed rules _None_ #### Edited rules -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 100, 2, {"ignoreUrls":true,"ignoreComments":false}] -- - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] - - [2, {"defaultAssignment":false}] -- - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] - - [2, {"defaultAssignment":false}] -- - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, {"anonymous":"never","named":"never"}] - - [2, {"anonymous":"always","named":"never"}] +_None_ diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index 37b1d2acae..a4b62f05be 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -170,10 +170,10 @@ function detailedDiff(ours, theirs, options) { const ruleDifferences = diffRules(ours.config, theirs.config, options); const otherDifferences = diffEverythingElse(ours.config, theirs.config, options); - function organizePartitions(rules) { - const categories = _.groupBy(rules, 'category'); + function organizePartitions(partitionedRules) { + const categories = _.groupBy(partitionedRules, 'category'); - function groupRules() { + function groupRules(rules) { const groupedRules = _(rules) .sortBy('name') .groupBy('changeType').value(); From 76b3e2fbefd0ba3cc543f5fb05b76aa6b793aa1e Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 19:55:20 -0700 Subject: [PATCH 32/71] Fix linting errors --- packages/eslint-config-hudl/.eslintignore | 1 + packages/eslint-config-hudl/tasks/docs.js | 3 +-- packages/eslint-config-hudl/tasks/lint.js | 2 +- packages/eslint-config-hudl/test/original/.eslintrc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 packages/eslint-config-hudl/.eslintignore diff --git a/packages/eslint-config-hudl/.eslintignore b/packages/eslint-config-hudl/.eslintignore new file mode 100644 index 0000000000..a9a1bd38ab --- /dev/null +++ b/packages/eslint-config-hudl/.eslintignore @@ -0,0 +1 @@ +reports/ diff --git a/packages/eslint-config-hudl/tasks/docs.js b/packages/eslint-config-hudl/tasks/docs.js index bfee94efd1..280bd2196b 100644 --- a/packages/eslint-config-hudl/tasks/docs.js +++ b/packages/eslint-config-hudl/tasks/docs.js @@ -1,6 +1,5 @@ -const path = require('path') const gulp = require('gulp'); -const writeDocs = require('./docs/writeDocs') +const writeDocs = require('./docs/writeDocs'); gulp.task('docs', function() { return writeDocs(); diff --git a/packages/eslint-config-hudl/tasks/lint.js b/packages/eslint-config-hudl/tasks/lint.js index c000782eef..0023333c8e 100644 --- a/packages/eslint-config-hudl/tasks/lint.js +++ b/packages/eslint-config-hudl/tasks/lint.js @@ -4,7 +4,7 @@ const gulpIf = require('gulp-if'); function isFixed(file) { // Has ESLint fixed the file contents? - return file.eslint !== null && file.eslint.fixed; + return file.eslint && file.eslint.fixed; } gulp.task('lint', function() { diff --git a/packages/eslint-config-hudl/test/original/.eslintrc b/packages/eslint-config-hudl/test/original/.eslintrc index a9ccc201dd..c667e5f9bc 100644 --- a/packages/eslint-config-hudl/test/original/.eslintrc +++ b/packages/eslint-config-hudl/test/original/.eslintrc @@ -1,6 +1,6 @@ { "root": true, - "extends": '../base.js', + "extends": '../../base.js', "rules": { // disabled because I find it tedious to write tests while following this // rule From 2740f3bf8a704bd17373da789c0db005d74faf8f Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 20:04:04 -0700 Subject: [PATCH 33/71] Add mocha-teamcity-reporter, fix docs --- .../comparisons/before-packaging-refactor.md | 392 +++++++++++++++++- .../docs/comparisons/with-airbnb-master.md | 21 +- packages/eslint-config-hudl/package.json | 1 + .../tasks/docs/diffs/ConfigDiff.js | 2 +- 4 files changed, 411 insertions(+), 5 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index 0ad68cc6d3..e4ee841ab6 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -54,7 +54,395 @@ should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-r _None_ #### Removed rules -_None_ +- + [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) + - [0] +- + [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) + - [2, "never"] +- + [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) + - [2, "as-needed"] +- + [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) + - [0] +- + [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) + - [2, {"before":true,"after":true}] +- + [callback-return](http://eslint.org/docs/rules/callback-return.html) + - [0] +- + [complexity](http://eslint.org/docs/rules/complexity.html) + - [0, 11] +- + [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) + - [2, "never"] +- + [consistent-this](http://eslint.org/docs/rules/consistent-this.html) + - [0] +- + [constructor-super](http://eslint.org/docs/rules/constructor-super.html) + - [0] +- + [dot-location](http://eslint.org/docs/rules/dot-location.html) + - [0] +- + [func-style](http://eslint.org/docs/rules/func-style.html) + - [0] +- + [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) + - [0] +- + [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) + - [0] +- + [id-length](http://eslint.org/docs/rules/id-length.html) + - [0] +- + [id-match](http://eslint.org/docs/rules/id-match.html) + - [0] +- + [init-declarations](http://eslint.org/docs/rules/init-declarations.html) + - [0] +- + [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) + - [0] +- + [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) + - [0] +- + [max-depth](http://eslint.org/docs/rules/max-depth.html) + - [0, 4] +- + [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) + - [0] +- + [max-params](http://eslint.org/docs/rules/max-params.html) + - [0, 3] +- + [max-statements](http://eslint.org/docs/rules/max-statements.html) + - [0, 10] +- + [new-parens](http://eslint.org/docs/rules/new-parens.html) + - [0] +- + [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) + - [0] +- + [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) + - [0] +- + [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) + - [0] +- + [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) + - [0] +- + [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) + - [0] +- + [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) + - [2] +- + [no-continue](http://eslint.org/docs/rules/no-continue.html) + - [0] +- + [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) + - [2] +- + [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) + - [2] +- + [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) + - [0] +- + [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) + - [2] +- + [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) + - [2] +- + [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) + - [2] +- + [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) + - [0] +- + [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) + - [0] +- + [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) + - [0] +- + [no-iterator](http://eslint.org/docs/rules/no-iterator.html) + - [2] +- + [no-label-var](http://eslint.org/docs/rules/no-label-var.html) + - [0] +- + [no-labels](http://eslint.org/docs/rules/no-labels.html) + - [2] +- + [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) + - [0] +- + [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) + - [0, false] +- + [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) + - [2] +- + [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) + - [2] +- + [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) + - [2] +- + [no-new-require](http://eslint.org/docs/rules/no-new-require.html) + - [0] +- + [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) + - [0] +- + [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) + - [0] +- + [no-process-env](http://eslint.org/docs/rules/no-process-env.html) + - [0] +- + [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) + - [0] +- + [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) + - [2] +- + [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) + - [0] +- + [no-sync](http://eslint.org/docs/rules/no-sync.html) + - [0] +- + [no-ternary](http://eslint.org/docs/rules/no-ternary.html) + - [0] +- + [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) + - [0] +- + [no-undef](http://eslint.org/docs/rules/no-undef.html) + - [2] +- + [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) + - [0] +- + [no-undefined](http://eslint.org/docs/rules/no-undefined.html) + - [0] +- + [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) + - [0] +- + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] +- + [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) + - [2] +- + [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) + - [0] +- + [no-void](http://eslint.org/docs/rules/no-void.html) + - [0] +- + [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) + - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] +- + [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) + - [2, "always"] +- + [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) + - [2, "always"] +- + [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) + - [0] +- + [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) + - [0] +- + [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) + - [2] +- + [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) + - [0] +- + [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) + - [0] +- + [prefer-template](http://eslint.org/docs/rules/prefer-template.html) + - [2] +- + [require-yield](http://eslint.org/docs/rules/require-yield.html) + - [0] +- + [sort-vars](http://eslint.org/docs/rules/sort-vars.html) + - [0] +- + [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) + - [2, "always"] +- + [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) + - [2, "never"] +- + [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) + - [0] +- + [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) + - [0] +- + [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) + - [2] +- + [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) + - [0] #### Edited rules -_None_ +- + [indent](http://eslint.org/docs/rules/indent.html) + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] + - [2, 2] +- + [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) + - [2, "prefer-double"] + - [2] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] +- + [new-cap](http://eslint.org/docs/rules/new-cap.html) + - [2, {"newIsCap":true}] + - [2, {"newIsCap":true,"capIsNew":false}] +- + [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) + - [0] + - [2] +- + [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) + - [2, {"max":2,"maxEOF":1}] + - [2, {"max":2}] +- + [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) + - [2, {"props":true}] + - [2] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] + - [2, "consistent"] +- react/display-name + - [0, {"acceptTranspilerName":false}] + - [0] +- react/forbid-prop-types + - [0, {"forbid":["any","array","object"]}] + - [0] +- react/jsx-boolean-value + - [2, "never"] + - [2] +- react/jsx-closing-bracket-location + - [2, "line-aligned"] + - [0] +- react/jsx-closing-bracket-location + - [2, "line-aligned"] + - [0] +- react/jsx-curly-spacing + - [0, "never", {"allowMultiline":true}] + - [0] +- react/jsx-curly-spacing + - [0, "never", {"allowMultiline":true}] + - [0] +- react/jsx-handler-names + - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] + - [0] +- react/jsx-indent-props + - [2, 2] + - [0] +- react/jsx-indent-props + - [2, 2] + - [0] +- react/jsx-max-props-per-line + - [0, {"maximum":1}] + - [0] +- react/jsx-no-bind + - [2] + - [0] +- react/jsx-no-duplicate-props + - [0, {"ignoreCase":false}] + - [0] +- react/jsx-sort-prop-types + - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0] +- react/jsx-sort-props + - [0, {"ignoreCase":false,"callbacksLast":false}] + - [0] +- react/jsx-uses-react + - [2, {"pragma":"React"}] + - [2] +- react/no-deprecated + - [1, {"react":"0.14.0"}] + - [0] +- react/no-deprecated + - [1, {"react":"0.14.0"}] + - [0] +- react/no-did-update-set-state + - [2, "allow-in-func"] + - [2] +- react/no-is-mounted + - [2] + - [0] +- react/no-multi-comp + - [2, {"ignoreStateless":true}] + - [2] +- react/prefer-es6-class + - [2, "always"] + - [0] +- react/prefer-es6-class + - [2, "always"] + - [0] +- react/prop-types + - [2, {"ignore":[],"customValidators":[]}] + - [2] +- react/require-extension + - [0, {"extensions":[".jsx"]}] + - [0] +- react/sort-comp + - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] + - [2] +- react/wrap-multilines + - [2, {"declaration":true,"assignment":true,"return":true}] + - [2] +- + [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) + - [2, "always"] + - [2] +- + [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) + - [2, {"anonymous":"never","named":"never"}] + - [2, "never"] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] + - [2] +- + [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) + - [2, "outside"] + - [2, "any"] diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index 43cb9ca2a2..b1c6c43197 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -40,10 +40,27 @@ _None_ #### Added rules -_None_ +- + [no-case-declarations](http://eslint.org/docs/rules/no-case-declarations.html) + - [2] #### Removed rules _None_ #### Edited rules -_None_ +- + [max-len](http://eslint.org/docs/rules/max-len.html) + - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 100, 2, {"ignoreUrls":true,"ignoreComments":false}] +- + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] + - [2, {"defaultAssignment":false}] +- + [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + - [0] + - [2, {"defaultAssignment":false}] +- + [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) + - [2, {"anonymous":"never","named":"never"}] + - [2, {"anonymous":"always","named":"never"}] diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index ae733a6e89..3683688c9b 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -78,6 +78,7 @@ "gulp-mocha": "^2.2.0", "handlebars": "^4.0.5", "lodash": "^4.2.1", + "mocha-teamcity-reporter": "^1.0.0", "react": "^0.13.3", "request-promise": "^2.0.0", "require-dir": "^0.3.0", diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index a4b62f05be..4950ec7627 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -193,7 +193,7 @@ function detailedDiff(ours, theirs, options) { } return { - ruleGroups: groupRules(categories.rules), + ruleGroups: groupRules(categories.rule), otherItems: categories.other, }; } From f70965c97f02422b9047113e274fe71747250abe Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 20:12:25 -0700 Subject: [PATCH 34/71] Filter out removed disabled rules --- .../comparisons/before-packaging-refactor.md | 156 ------------------ .../tasks/docs/diffs/ConfigDiff.js | 8 +- 2 files changed, 7 insertions(+), 157 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index e4ee841ab6..e7ee536c3d 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -54,108 +54,39 @@ should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-r _None_ #### Removed rules -- - [accessor-pairs](http://eslint.org/docs/rules/accessor-pairs.html) - - [0] - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - [2, "never"] - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - [2, "as-needed"] -- - [arrow-parens](http://eslint.org/docs/rules/arrow-parens.html) - - [0] - [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) - [2, {"before":true,"after":true}] -- - [callback-return](http://eslint.org/docs/rules/callback-return.html) - - [0] - [complexity](http://eslint.org/docs/rules/complexity.html) - [0, 11] - [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) - [2, "never"] -- - [consistent-this](http://eslint.org/docs/rules/consistent-this.html) - - [0] -- - [constructor-super](http://eslint.org/docs/rules/constructor-super.html) - - [0] -- - [dot-location](http://eslint.org/docs/rules/dot-location.html) - - [0] -- - [func-style](http://eslint.org/docs/rules/func-style.html) - - [0] -- - [generator-star-spacing](http://eslint.org/docs/rules/generator-star-spacing.html) - - [0] -- - [handle-callback-err](http://eslint.org/docs/rules/handle-callback-err.html) - - [0] -- - [id-length](http://eslint.org/docs/rules/id-length.html) - - [0] -- - [id-match](http://eslint.org/docs/rules/id-match.html) - - [0] -- - [init-declarations](http://eslint.org/docs/rules/init-declarations.html) - - [0] -- - [linebreak-style](http://eslint.org/docs/rules/linebreak-style.html) - - [0] -- - [lines-around-comment](http://eslint.org/docs/rules/lines-around-comment.html) - - [0] - [max-depth](http://eslint.org/docs/rules/max-depth.html) - [0, 4] -- - [max-nested-callbacks](http://eslint.org/docs/rules/max-nested-callbacks.html) - - [0] - [max-params](http://eslint.org/docs/rules/max-params.html) - [0, 3] - [max-statements](http://eslint.org/docs/rules/max-statements.html) - [0, 10] -- - [new-parens](http://eslint.org/docs/rules/new-parens.html) - - [0] -- - [newline-after-var](http://eslint.org/docs/rules/newline-after-var.html) - - [0] -- - [no-array-constructor](http://eslint.org/docs/rules/no-array-constructor.html) - - [0] -- - [no-bitwise](http://eslint.org/docs/rules/no-bitwise.html) - - [0] -- - [no-catch-shadow](http://eslint.org/docs/rules/no-catch-shadow.html) - - [0] -- - [no-class-assign](http://eslint.org/docs/rules/no-class-assign.html) - - [0] - [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - [2] -- - [no-continue](http://eslint.org/docs/rules/no-continue.html) - - [0] - [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) - [2] - [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) - [2] -- - [no-div-regex](http://eslint.org/docs/rules/no-div-regex.html) - - [0] - [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) - [2] @@ -165,27 +96,12 @@ _None_ - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - [2] -- - [no-implicit-coercion](http://eslint.org/docs/rules/no-implicit-coercion.html) - - [0] -- - [no-inline-comments](http://eslint.org/docs/rules/no-inline-comments.html) - - [0] -- - [no-invalid-this](http://eslint.org/docs/rules/no-invalid-this.html) - - [0] - [no-iterator](http://eslint.org/docs/rules/no-iterator.html) - [2] -- - [no-label-var](http://eslint.org/docs/rules/no-label-var.html) - - [0] - [no-labels](http://eslint.org/docs/rules/no-labels.html) - [2] -- - [no-lonely-if](http://eslint.org/docs/rules/no-lonely-if.html) - - [0] - [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) - [0, false] @@ -198,60 +114,15 @@ _None_ - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) - [2] -- - [no-new-require](http://eslint.org/docs/rules/no-new-require.html) - - [0] -- - [no-path-concat](http://eslint.org/docs/rules/no-path-concat.html) - - [0] -- - [no-plusplus](http://eslint.org/docs/rules/no-plusplus.html) - - [0] -- - [no-process-env](http://eslint.org/docs/rules/no-process-env.html) - - [0] -- - [no-process-exit](http://eslint.org/docs/rules/no-process-exit.html) - - [0] - [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) - [2] -- - [no-restricted-modules](http://eslint.org/docs/rules/no-restricted-modules.html) - - [0] -- - [no-sync](http://eslint.org/docs/rules/no-sync.html) - - [0] -- - [no-ternary](http://eslint.org/docs/rules/no-ternary.html) - - [0] -- - [no-this-before-super](http://eslint.org/docs/rules/no-this-before-super.html) - - [0] - [no-undef](http://eslint.org/docs/rules/no-undef.html) - [2] -- - [no-undef-init](http://eslint.org/docs/rules/no-undef-init.html) - - [0] -- - [no-undefined](http://eslint.org/docs/rules/no-undefined.html) - - [0] -- - [no-unexpected-multiline](http://eslint.org/docs/rules/no-unexpected-multiline.html) - - [0] -- - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - - [0] - [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) - [2] -- - [no-useless-call](http://eslint.org/docs/rules/no-useless-call.html) - - [0] -- - [no-void](http://eslint.org/docs/rules/no-void.html) - - [0] - [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] @@ -261,48 +132,21 @@ _None_ - [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) - [2, "always"] -- - [operator-assignment](http://eslint.org/docs/rules/operator-assignment.html) - - [0] -- - [operator-linebreak](http://eslint.org/docs/rules/operator-linebreak.html) - - [0] - [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) - [2] -- - [prefer-reflect](http://eslint.org/docs/rules/prefer-reflect.html) - - [0] -- - [prefer-spread](http://eslint.org/docs/rules/prefer-spread.html) - - [0] - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - [2] -- - [require-yield](http://eslint.org/docs/rules/require-yield.html) - - [0] -- - [sort-vars](http://eslint.org/docs/rules/sort-vars.html) - - [0] - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - [2, "always"] - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - [2, "never"] -- - [space-unary-ops](http://eslint.org/docs/rules/space-unary-ops.html) - - [0] -- - [valid-jsdoc](http://eslint.org/docs/rules/valid-jsdoc.html) - - [0] - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - [2] -- - [wrap-regex](http://eslint.org/docs/rules/wrap-regex.html) - - [0] #### Edited rules - diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index 4950ec7627..2c5bc5b689 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -35,6 +35,7 @@ function diffRules(ourConfig, theirConfig, options) { var valueArrays; var changeType; var isKnown; + var isIgnorable = false; function diffValueChanges(thisSet, otherSet, flag) { return thisSet.map(function(value, i) { @@ -62,6 +63,8 @@ function diffRules(ourConfig, theirConfig, options) { } else if (change.kind === 'D' && change.path.length === 1) { changeType = 'removed'; isKnown = ruleOptions.removed && _.includes(ruleOptions.removed, change.path[0]); + // The rule has been removed, but it was disabled anyway + isIgnorable = _.isEqual(change.lhs, [0]); valueArrays = [ change.lhs.map(function(value) { return { @@ -110,10 +113,13 @@ function diffRules(ourConfig, theirConfig, options) { isKnown: isKnown, valueArrays: valueArrays, category: 'rule', + isIgnorable: isIgnorable, }; }); - return ruleDifferences; + return ruleDifferences.filter(function(change) { + return !change.isIgnorable; + }); } function diffEverythingElse(ourConfig, theirConfig /* , options */ ) { From 1eff90e9981b5878a909a1304cabaaeec9b787af Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Thu, 4 Feb 2016 20:43:26 -0700 Subject: [PATCH 35/71] Change new rules back to current standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - We will be able to revisit this later by comparing by Airbnb’s current version and then recording known differences. --- .../comparisons/before-packaging-refactor.md | 236 +----------------- .../docs/comparisons/with-airbnb-master.md | 185 +++++++++++++- .../rules/best-practices.js | 18 +- packages/eslint-config-hudl/rules/errors.js | 12 +- packages/eslint-config-hudl/rules/es6.js | 15 +- packages/eslint-config-hudl/rules/react.js | 46 +--- packages/eslint-config-hudl/rules/style.js | 44 ++-- .../eslint-config-hudl/rules/variables.js | 4 +- .../tasks/docs/diffs/ConfigDiff.js | 12 +- 9 files changed, 239 insertions(+), 333 deletions(-) diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index e7ee536c3d..0ad68cc6d3 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -54,239 +54,7 @@ should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-r _None_ #### Removed rules -- - [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) - - [2, "never"] -- - [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) - - [2, "as-needed"] -- - [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) - - [2, {"before":true,"after":true}] -- - [complexity](http://eslint.org/docs/rules/complexity.html) - - [0, 11] -- - [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) - - [2, "never"] -- - [max-depth](http://eslint.org/docs/rules/max-depth.html) - - [0, 4] -- - [max-params](http://eslint.org/docs/rules/max-params.html) - - [0, 3] -- - [max-statements](http://eslint.org/docs/rules/max-statements.html) - - [0, 10] -- - [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - - [2] -- - [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) - - [2] -- - [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) - - [2] -- - [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) - - [2] -- - [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) - - [2] -- - [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) - - [2] -- - [no-iterator](http://eslint.org/docs/rules/no-iterator.html) - - [2] -- - [no-labels](http://eslint.org/docs/rules/no-labels.html) - - [2] -- - [no-mixed-requires](http://eslint.org/docs/rules/no-mixed-requires.html) - - [0, false] -- - [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) - - [2] -- - [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) - - [2] -- - [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) - - [2] -- - [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) - - [2] -- - [no-undef](http://eslint.org/docs/rules/no-undef.html) - - [2] -- - [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) - - [2] -- - [no-warning-comments](http://eslint.org/docs/rules/no-warning-comments.html) - - [0, {"terms":["todo","fixme","xxx"],"location":"start"}] -- - [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) - - [2, "always"] -- - [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) - - [2, "always"] -- - [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) - - [2] -- - [prefer-template](http://eslint.org/docs/rules/prefer-template.html) - - [2] -- - [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) - - [2, "always"] -- - [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) - - [2, "never"] -- - [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) - - [2] +_None_ #### Edited rules -- - [indent](http://eslint.org/docs/rules/indent.html) - - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] - - [2, 2] -- - [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) - - [2, "prefer-double"] - - [2] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 120, 4] -- - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 120, 4] -- - [new-cap](http://eslint.org/docs/rules/new-cap.html) - - [2, {"newIsCap":true}] - - [2, {"newIsCap":true,"capIsNew":false}] -- - [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) - - [0] - - [2] -- - [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) - - [2, {"max":2,"maxEOF":1}] - - [2, {"max":2}] -- - [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) - - [2, {"props":true}] - - [2] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - - [2, "consistent"] -- - [quote-props](http://eslint.org/docs/rules/quote-props.html) - - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] - - [2, "consistent"] -- react/display-name - - [0, {"acceptTranspilerName":false}] - - [0] -- react/forbid-prop-types - - [0, {"forbid":["any","array","object"]}] - - [0] -- react/jsx-boolean-value - - [2, "never"] - - [2] -- react/jsx-closing-bracket-location - - [2, "line-aligned"] - - [0] -- react/jsx-closing-bracket-location - - [2, "line-aligned"] - - [0] -- react/jsx-curly-spacing - - [0, "never", {"allowMultiline":true}] - - [0] -- react/jsx-curly-spacing - - [0, "never", {"allowMultiline":true}] - - [0] -- react/jsx-handler-names - - [0, {"eventHandlerPrefix":"handle","eventHandlerPropPrefix":"on"}] - - [0] -- react/jsx-indent-props - - [2, 2] - - [0] -- react/jsx-indent-props - - [2, 2] - - [0] -- react/jsx-max-props-per-line - - [0, {"maximum":1}] - - [0] -- react/jsx-no-bind - - [2] - - [0] -- react/jsx-no-duplicate-props - - [0, {"ignoreCase":false}] - - [0] -- react/jsx-sort-prop-types - - [0, {"ignoreCase":false,"callbacksLast":false}] - - [0] -- react/jsx-sort-props - - [0, {"ignoreCase":false,"callbacksLast":false}] - - [0] -- react/jsx-uses-react - - [2, {"pragma":"React"}] - - [2] -- react/no-deprecated - - [1, {"react":"0.14.0"}] - - [0] -- react/no-deprecated - - [1, {"react":"0.14.0"}] - - [0] -- react/no-did-update-set-state - - [2, "allow-in-func"] - - [2] -- react/no-is-mounted - - [2] - - [0] -- react/no-multi-comp - - [2, {"ignoreStateless":true}] - - [2] -- react/prefer-es6-class - - [2, "always"] - - [0] -- react/prefer-es6-class - - [2, "always"] - - [0] -- react/prop-types - - [2, {"ignore":[],"customValidators":[]}] - - [2] -- react/require-extension - - [0, {"extensions":[".jsx"]}] - - [0] -- react/sort-comp - - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] - - [2] -- react/wrap-multilines - - [2, {"declaration":true,"assignment":true,"return":true}] - - [2] -- - [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) - - [2, "always"] - - [2] -- - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, {"anonymous":"never","named":"never"}] - - [2, "never"] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - - [2] -- - [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) - - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] - - [2] -- - [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) - - [2, "outside"] - - [2, "any"] +_None_ diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index b1c6c43197..3ffbb7697c 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -48,19 +48,194 @@ _None_ _None_ #### Edited rules +- + [array-bracket-spacing](http://eslint.org/docs/rules/array-bracket-spacing.html) + - [0] + - [2, "never"] +- + [arrow-body-style](http://eslint.org/docs/rules/arrow-body-style.html) + - [0] + - [2, "as-needed"] +- + [arrow-spacing](http://eslint.org/docs/rules/arrow-spacing.html) + - [0] + - [2, {"before":true,"after":true}] +- + [computed-property-spacing](http://eslint.org/docs/rules/computed-property-spacing.html) + - [0] + - [2, "never"] +- + [indent](http://eslint.org/docs/rules/indent.html) + - [2, 2] + - [2, 2, {"SwitchCase":1,"VariableDeclarator":1}] +- + [jsx-quotes](http://eslint.org/docs/rules/jsx-quotes.html) + - [2] + - [2, "prefer-double"] - [max-len](http://eslint.org/docs/rules/max-len.html) - - [2, 120, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [2, 100, 2, {"ignoreUrls":true,"ignoreComments":false}] + - [2, 120, 4] + - [2, 100, 2, {"ignoreUrls":true,"ignoreComments":false}] - - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) + [new-cap](http://eslint.org/docs/rules/new-cap.html) + - [2, {"newIsCap":true,"capIsNew":false}] + - [2, {"newIsCap":true}] +- + [no-const-assign](http://eslint.org/docs/rules/no-const-assign.html) - [0] - - [2, {"defaultAssignment":false}] + - [2] +- + [no-control-regex](http://eslint.org/docs/rules/no-control-regex.html) + - [0] + - [2] +- + [no-delete-var](http://eslint.org/docs/rules/no-delete-var.html) + - [0] + - [2] +- + [no-dupe-args](http://eslint.org/docs/rules/no-dupe-args.html) + - [0] + - [2] +- + [no-empty-character-class](http://eslint.org/docs/rules/no-empty-character-class.html) + - [0] + - [2] +- + [no-empty-label](http://eslint.org/docs/rules/no-empty-label.html) + - [0] + - [2] +- + [no-eq-null](http://eslint.org/docs/rules/no-eq-null.html) + - [2] + - [0] +- + [no-iterator](http://eslint.org/docs/rules/no-iterator.html) + - [0] + - [2] +- + [no-labels](http://eslint.org/docs/rules/no-labels.html) + - [0] + - [2] +- + [no-mixed-spaces-and-tabs](http://eslint.org/docs/rules/no-mixed-spaces-and-tabs.html) + - [0] + - [2] +- + [no-multi-spaces](http://eslint.org/docs/rules/no-multi-spaces.html) + - [0] + - [2] +- + [no-multiple-empty-lines](http://eslint.org/docs/rules/no-multiple-empty-lines.html) + - [2, {"max":2}] + - [2, {"max":2,"maxEOF":1}] +- + [no-negated-in-lhs](http://eslint.org/docs/rules/no-negated-in-lhs.html) + - [0] + - [2] +- + [no-param-reassign](http://eslint.org/docs/rules/no-param-reassign.html) + - [2] + - [2, {"props":true}] +- + [no-regex-spaces](http://eslint.org/docs/rules/no-regex-spaces.html) + - [0] + - [2] +- + [no-undef](http://eslint.org/docs/rules/no-undef.html) + - [0] + - [2] - [no-unneeded-ternary](http://eslint.org/docs/rules/no-unneeded-ternary.html) - [0] - [2, {"defaultAssignment":false}] +- + [no-unused-expressions](http://eslint.org/docs/rules/no-unused-expressions.html) + - [0] + - [2] +- + [object-curly-spacing](http://eslint.org/docs/rules/object-curly-spacing.html) + - [0, "always"] + - [2, "always"] +- + [object-shorthand](http://eslint.org/docs/rules/object-shorthand.html) + - [0, "always"] + - [2, "always"] +- + [prefer-arrow-callback](http://eslint.org/docs/rules/prefer-arrow-callback.html) + - [0] + - [2] +- + [prefer-template](http://eslint.org/docs/rules/prefer-template.html) + - [0] + - [2] +- + [quote-props](http://eslint.org/docs/rules/quote-props.html) + - [2, "consistent"] + - [2, "as-needed", {"keywords":false,"unnecessary":true,"numbers":false}] +- react/jsx-boolean-value + - [2] + - [2, "never"] +- react/jsx-closing-bracket-location + - [0, "line-aligned"] + - [2, "line-aligned"] +- react/jsx-indent-props + - [0, 2] + - [2, 2] +- react/jsx-no-bind + - [0] + - [2] +- react/jsx-uses-react + - [2] + - [2, {"pragma":"React"}] +- react/no-deprecated + - [0, {"react":"0.14.0"}] + - [1, {"react":"0.14.0"}] +- react/no-did-update-set-state + - [2] + - [2, "allow-in-func"] +- react/no-is-mounted + - [0] + - [2] +- react/no-multi-comp + - [2] + - [2, {"ignoreStateless":true}] +- react/prefer-es6-class + - [0] + - [2, "always"] +- react/prop-types + - [2] + - [2, {"ignore":[],"customValidators":[]}] +- react/sort-comp + - [2] + - [2, {"order":["lifecycle","/^on.+$/","/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/","everything-else","/^render.+$/","render"]}] +- react/wrap-multilines + - [2] + - [2, {"declaration":true,"assignment":true,"return":true}] +- + [space-after-keywords](http://eslint.org/docs/rules/space-after-keywords.html) + - [2] + - [2, "always"] - [space-before-function-paren](http://eslint.org/docs/rules/space-before-function-paren.html) - - [2, {"anonymous":"never","named":"never"}] + - [2, "never"] - [2, {"anonymous":"always","named":"never"}] +- + [space-before-keywords](http://eslint.org/docs/rules/space-before-keywords.html) + - [0, "always"] + - [2, "always"] +- + [space-in-parens](http://eslint.org/docs/rules/space-in-parens.html) + - [0, "never"] + - [2, "never"] +- + [spaced-comment](http://eslint.org/docs/rules/spaced-comment.html) + - [2] + - [2, "always", {"exceptions":["-","+"],"markers":["=","!"]}] +- + [valid-typeof](http://eslint.org/docs/rules/valid-typeof.html) + - [0] + - [2] +- + [wrap-iife](http://eslint.org/docs/rules/wrap-iife.html) + - [2, "any"] + - [2, "outside"] diff --git a/packages/eslint-config-hudl/rules/best-practices.js b/packages/eslint-config-hudl/rules/best-practices.js index dfb1ada5f6..f6a59f5c77 100644 --- a/packages/eslint-config-hudl/rules/best-practices.js +++ b/packages/eslint-config-hudl/rules/best-practices.js @@ -31,9 +31,9 @@ module.exports = { // disallow else after a return in an if 'no-else-return': 2, // disallow use of labels for anything other then loops and switches - 'no-empty-label': 2, + 'no-empty-label': 0, // disallow comparisons to null without a type-checking operator - 'no-eq-null': 0, + 'no-eq-null': 2, // disallow use of eval() 'no-eval': 2, // disallow adding to native types @@ -51,15 +51,15 @@ module.exports = { // disallow this keywords outside of classes or class-like objects 'no-invalid-this': 0, // disallow usage of __iterator__ property - 'no-iterator': 2, + 'no-iterator': 0, // disallow use of labeled statements - 'no-labels': 2, + 'no-labels': 0, // disallow unnecessary nested blocks 'no-lone-blocks': 2, // disallow creation of functions within loops 'no-loop-func': 2, // disallow use of multiple spaces - 'no-multi-spaces': 2, + 'no-multi-spaces': 0, // disallow use of multiline strings 'no-multi-str': 2, // disallow reassignments of native objects @@ -78,9 +78,7 @@ module.exports = { // disallow reassignment of function parameters // disallow parameter object manipulation // rule: http://eslint.org/docs/rules/no-param-reassign.html - 'no-param-reassign': [2, { - 'props': true, - }], + 'no-param-reassign': [2], // disallow use of process.env 'no-process-env': 0, // disallow usage of __proto__ property @@ -98,7 +96,7 @@ module.exports = { // restrict what can be thrown as an exception 'no-throw-literal': 2, // disallow usage of expressions in statement position - 'no-unused-expressions': 2, + 'no-unused-expressions': 0, // disallow unnecessary .call() and .apply() 'no-useless-call': 0, // disallow use of void operator @@ -116,7 +114,7 @@ module.exports = { 'vars-on-top': 2, // require immediate function invocation to be wrapped in parentheses // http://eslint.org/docs/rules/wrap-iife.html - 'wrap-iife': [2, 'outside'], + 'wrap-iife': [2, 'any'], // require or disallow Yoda conditions 'yoda': 2, }, diff --git a/packages/eslint-config-hudl/rules/errors.js b/packages/eslint-config-hudl/rules/errors.js index 2b55560f0b..54d91cc8b4 100644 --- a/packages/eslint-config-hudl/rules/errors.js +++ b/packages/eslint-config-hudl/rules/errors.js @@ -9,17 +9,17 @@ module.exports = { // disallow use of constant expressions in conditions 'no-constant-condition': 1, // disallow control characters in regular expressions - 'no-control-regex': 2, + 'no-control-regex': 0, // disallow use of debugger 'no-debugger': 1, // disallow duplicate arguments in functions - 'no-dupe-args': 2, + 'no-dupe-args': 0, // disallow duplicate keys when creating object literals 'no-dupe-keys': 2, // disallow a duplicate case label. 'no-duplicate-case': 2, // disallow the use of empty character classes in regular expressions - 'no-empty-character-class': 2, + 'no-empty-character-class': 0, // disallow empty statements 'no-empty': 2, // disallow assigning to the exception in a catch block @@ -39,11 +39,11 @@ module.exports = { // disallow irregular whitespace outside of strings and comments 'no-irregular-whitespace': 2, // disallow negation of the left operand of an in expression - 'no-negated-in-lhs': 2, + 'no-negated-in-lhs': 0, // disallow the use of object properties of the global object (Math and JSON) as functions 'no-obj-calls': 2, // disallow multiple spaces in a regular expression literal - 'no-regex-spaces': 2, + 'no-regex-spaces': 0, // disallow sparse arrays 'no-sparse-arrays': 2, // disallow unreachable statements after a return, throw, continue, or break statement @@ -53,7 +53,7 @@ module.exports = { // ensure JSDoc comments are valid 'valid-jsdoc': 0, // ensure that the results of typeof are compared against a valid string - 'valid-typeof': 2, + 'valid-typeof': 0, // Avoid code that looks like two expressions but is actually one 'no-unexpected-multiline': 0, }, diff --git a/packages/eslint-config-hudl/rules/es6.js b/packages/eslint-config-hudl/rules/es6.js index 27ecfdb00b..d229dff58b 100644 --- a/packages/eslint-config-hudl/rules/es6.js +++ b/packages/eslint-config-hudl/rules/es6.js @@ -24,15 +24,12 @@ module.exports = { 'rules': { // enforces no braces where they can be omitted // http://eslint.org/docs/rules/arrow-body-style - 'arrow-body-style': [2, 'as-needed'], + 'arrow-body-style': 0, // require parens in arrow function arguments 'arrow-parens': 0, // require space before/after arrow function's arrow // https://github.com/eslint/eslint/blob/master/docs/rules/arrow-spacing.md - 'arrow-spacing': [2, { - 'before': true, - 'after': true, - }], + 'arrow-spacing': 0, // verify super() callings in constructors 'constructor-super': 0, // enforce the spacing around the * in generator functions @@ -40,16 +37,16 @@ module.exports = { // disallow modifying variables of class declarations 'no-class-assign': 0, // disallow modifying variables that are declared using const - 'no-const-assign': 2, + 'no-const-assign': 0, // disallow to use this/super before super() calling in constructors. 'no-this-before-super': 0, // require let or const instead of var 'no-var': 2, // require method and property shorthand syntax for object literals // https://github.com/eslint/eslint/blob/master/docs/rules/object-shorthand.md - 'object-shorthand': [2, 'always'], + 'object-shorthand': [0, 'always'], // suggest using arrow functions as callbacks - 'prefer-arrow-callback': 2, + 'prefer-arrow-callback': 0, // suggest using of const declaration for variables that are never modified after declared 'prefer-const': 2, // suggest using the spread operator instead of .apply() @@ -58,7 +55,7 @@ module.exports = { 'prefer-reflect': 0, // suggest using template literals instead of string concatenation // http://eslint.org/docs/rules/prefer-template - 'prefer-template': 2, + 'prefer-template': 0, // disallow generator functions that do not have yield 'require-yield': 0, }, diff --git a/packages/eslint-config-hudl/rules/react.js b/packages/eslint-config-hudl/rules/react.js index 62b16aeda0..211ca01df0 100644 --- a/packages/eslint-config-hudl/rules/react.js +++ b/packages/eslint-config-hudl/rules/react.js @@ -20,10 +20,10 @@ module.exports = { }], // Enforce boolean attributes notation in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md - 'react/jsx-boolean-value': [2, 'never'], + 'react/jsx-boolean-value': [2], // Validate closing bracket location in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md - 'react/jsx-closing-bracket-location': [2, 'line-aligned'], + 'react/jsx-closing-bracket-location': [0, 'line-aligned'], // Enforce or disallow spaces inside of curly braces in JSX attributes // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md 'react/jsx-curly-spacing': [0, 'never', { @@ -37,7 +37,7 @@ module.exports = { }], // Validate props indentation in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md - 'react/jsx-indent-props': [2, 2], + 'react/jsx-indent-props': [0, 2], // Validate JSX has key prop when in array or iterator // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md 'react/jsx-key': 0, @@ -48,7 +48,7 @@ module.exports = { }], // Prevent usage of .bind() and arrow functions in JSX props // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md - 'react/jsx-no-bind': 2, + 'react/jsx-no-bind': 0, // Prevent duplicate props in JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md 'react/jsx-no-duplicate-props': [0, { @@ -77,9 +77,7 @@ module.exports = { }], // Prevent React to be incorrectly marked as unused // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md - 'react/jsx-uses-react': [2, { - 'pragma': 'React', - }], + 'react/jsx-uses-react': [2], // Prevent variables used in JSX to be incorrectly marked as unused // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md 'react/jsx-uses-vars': 2, @@ -88,7 +86,7 @@ module.exports = { 'react/no-danger': 0, // Prevent usage of deprecated methods // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md - 'react/no-deprecated': [1, { + 'react/no-deprecated': [0, { 'react': '0.14.0', }], // Prevent usage of setState in componentDidMount @@ -96,18 +94,16 @@ module.exports = { 'react/no-did-mount-set-state': [2, 'allow-in-func'], // Prevent usage of setState in componentDidUpdate // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md - 'react/no-did-update-set-state': [2, 'allow-in-func'], + 'react/no-did-update-set-state': [2], // Prevent direct mutation of this.state // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md 'react/no-direct-mutation-state': 0, // Prevent usage of isMounted // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md - 'react/no-is-mounted': 2, + 'react/no-is-mounted': 0, // Prevent multiple component definition per file // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md - 'react/no-multi-comp': [2, { - 'ignoreStateless': true, - }], + 'react/no-multi-comp': [2], // Prevent usage of setState // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md 'react/no-set-state': 0, @@ -119,13 +115,10 @@ module.exports = { 'react/no-unknown-property': 2, // Require ES6 class declarations over React.createClass // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md - 'react/prefer-es6-class': [2, 'always'], + 'react/prefer-es6-class': [0], // Prevent missing props validation in a React component definition // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md - 'react/prop-types': [2, { - 'ignore': [], - customValidators: [], - }], + 'react/prop-types': [2], // Prevent missing React when using JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md 'react/react-in-jsx-scope': 2, @@ -139,22 +132,9 @@ module.exports = { 'react/self-closing-comp': 2, // Enforce component methods order // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md - 'react/sort-comp': [2, { - 'order': [ - 'lifecycle', - '/^on.+$/', - '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', - 'everything-else', - '/^render.+$/', - 'render', - ], - }], + 'react/sort-comp': [2], // Prevent missing parentheses around multilines JSX // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md - 'react/wrap-multilines': [2, { - declaration: true, - assignment: true, - return: true, - }], + 'react/wrap-multilines': [2], }, }; diff --git a/packages/eslint-config-hudl/rules/style.js b/packages/eslint-config-hudl/rules/style.js index fd6e6e2b0d..a00c20e930 100644 --- a/packages/eslint-config-hudl/rules/style.js +++ b/packages/eslint-config-hudl/rules/style.js @@ -1,7 +1,7 @@ module.exports = { 'rules': { // enforce spacing inside array brackets - 'array-bracket-spacing': [2, 'never'], + 'array-bracket-spacing': 0, // enforce one true brace style 'brace-style': [2, '1tbs', { 'allowSingleLine': true, @@ -18,7 +18,7 @@ module.exports = { // enforce one true comma style 'comma-style': [2, 'last'], // disallow padding inside computed properties - 'computed-property-spacing': [2, 'never'], + 'computed-property-spacing': 0, // enforces consistent naming when capturing the current execution context 'consistent-this': 0, // enforce newline at the end of file, with no multiple empty lines @@ -32,13 +32,10 @@ module.exports = { 'id-length': 0, // this option sets a specific tab width for your code // https://github.com/eslint/eslint/blob/master/docs/rules/indent.md - 'indent': [2, 2, { - 'SwitchCase': 1, - 'VariableDeclarator': 1, - }], + 'indent': [2, 2], // specify whether double or single quotes should be used in JSX attributes // http://eslint.org/docs/rules/jsx-quotes - 'jsx-quotes': [2, 'prefer-double'], + 'jsx-quotes': [2], // enforces spacing between keys and values in object literal properties 'key-spacing': [2, { 'beforeColon': false, @@ -50,15 +47,13 @@ module.exports = { 'linebreak-style': 0, // specify the maximum length of a line in your program // https://github.com/eslint/eslint/blob/master/docs/rules/max-len.md - 'max-len': [2, 120, 2, { - 'ignoreUrls': true, - 'ignoreComments': false, - }], + 'max-len': [2, 120, 4], // specify the maximum depth callbacks can be nested 'max-nested-callbacks': 0, // require a capital letter for constructors 'new-cap': [2, { 'newIsCap': true, + 'capIsNew': false, }], // disallow the omission of parentheses when invoking a constructor with no arguments 'new-parens': 0, @@ -73,11 +68,10 @@ module.exports = { // disallow if as the only statement in an else block 'no-lonely-if': 0, // disallow mixed spaces and tabs for indentation - 'no-mixed-spaces-and-tabs': 2, + 'no-mixed-spaces-and-tabs': 0, // disallow multiple empty lines and only one newline at the end 'no-multiple-empty-lines': [2, { 'max': 2, - 'maxEOF': 1, }], // disallow nested ternary expressions 'no-nested-ternary': 2, @@ -94,7 +88,7 @@ module.exports = { // disallow the use of Boolean literals in conditional expressions 'no-unneeded-ternary': 0, // require padding inside curly braces - 'object-curly-spacing': [2, 'always'], + 'object-curly-spacing': [0, 'always'], // allow just one var statement per function 'one-var': [2, 'never'], // require assignment operator shorthand where possible or prohibit it entirely @@ -105,11 +99,7 @@ module.exports = { 'padded-blocks': [2, 'never'], // require quotes around object literal property names // http://eslint.org/docs/rules/quote-props.html - 'quote-props': [2, 'as-needed', { - 'keywords': false, - 'unnecessary': true, - 'numbers': false, - }], + 'quote-props': [2, 'consistent'], // specify whether double or single quotes should be used 'quotes': [2, 'single', 'avoid-escape'], // require identifiers to match the provided regular expression @@ -124,19 +114,16 @@ module.exports = { // sort variables within the same declaration block 'sort-vars': 0, // require a space before certain keywords - 'space-before-keywords': [2, 'always'], + 'space-before-keywords': [0, 'always'], // require a space after certain keywords - 'space-after-keywords': [2, 'always'], + 'space-after-keywords': [2], // require or disallow space before blocks 'space-before-blocks': 2, // require or disallow space before function opening parenthesis // https://github.com/eslint/eslint/blob/master/docs/rules/space-before-function-paren.md - 'space-before-function-paren': [2, { - 'anonymous': 'never', - 'named': 'never', - }], + 'space-before-function-paren': [2, 'never'], // require or disallow spaces inside parentheses - 'space-in-parens': [2, 'never'], + 'space-in-parens': [0, 'never'], // require spaces around operators 'space-infix-ops': 2, // require a space after return, throw, and case @@ -144,10 +131,7 @@ module.exports = { // Require or disallow spaces before/after unary operators 'space-unary-ops': 0, // require or disallow a space immediately following the // or /* in a comment - 'spaced-comment': [2, 'always', { - 'exceptions': ['-', '+'], - 'markers': ['=', '!'], // space here to support sprockets directives - }], + 'spaced-comment': [2], // require regex literals to be wrapped in parentheses 'wrap-regex': 0, }, diff --git a/packages/eslint-config-hudl/rules/variables.js b/packages/eslint-config-hudl/rules/variables.js index 848e8e6a1d..564bba2f8c 100644 --- a/packages/eslint-config-hudl/rules/variables.js +++ b/packages/eslint-config-hudl/rules/variables.js @@ -5,7 +5,7 @@ module.exports = { // disallow the catch clause parameter name being the same as a variable in the outer scope 'no-catch-shadow': 0, // disallow deletion of variables - 'no-delete-var': 2, + 'no-delete-var': 0, // disallow labels that share a name with a variable 'no-label-var': 0, // disallow shadowing of names such as arguments @@ -15,7 +15,7 @@ module.exports = { // disallow use of undefined when initializing variables 'no-undef-init': 0, // disallow use of undeclared variables unless mentioned in a /*global */ block - 'no-undef': 2, + 'no-undef': 0, // disallow use of undefined variable 'no-undefined': 0, // disallow declaration of variables that are not used in the code diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index 2c5bc5b689..6e69baffa6 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -64,7 +64,7 @@ function diffRules(ourConfig, theirConfig, options) { changeType = 'removed'; isKnown = ruleOptions.removed && _.includes(ruleOptions.removed, change.path[0]); // The rule has been removed, but it was disabled anyway - isIgnorable = _.isEqual(change.lhs, [0]); + isIgnorable = change.lhs[0] === 0; valueArrays = [ change.lhs.map(function(value) { return { @@ -79,6 +79,8 @@ function diffRules(ourConfig, theirConfig, options) { changeType = 'edited'; isKnown = ruleOptions.edited && _.isEqual(ruleOptions.edited[change.path[0]], newValue); + // Rule was and still is disabled, so we can ignore it's settings + isIgnorable = (prevValue[0] === 0) && (newValue[0] === 0); valueArrays = [ diffValueChanges(prevValue, newValue, 'removed'), @@ -117,9 +119,11 @@ function diffRules(ourConfig, theirConfig, options) { }; }); - return ruleDifferences.filter(function(change) { - return !change.isIgnorable; - }); + // Remove duplicates that are a side-effect of multiple subchanges + return _.uniqBy(ruleDifferences, 'name') + .filter(function(change) { + return !change.isIgnorable; + }); } function diffEverythingElse(ourConfig, theirConfig /* , options */ ) { From b6605304b2779ff88795068e3ce6c83f33e49be2 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Fri, 5 Feb 2016 09:44:38 -0700 Subject: [PATCH 36/71] Normalize path slashes for windows --- packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js index 6e69baffa6..59809da89a 100644 --- a/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js +++ b/packages/eslint-config-hudl/tasks/docs/diffs/ConfigDiff.js @@ -6,6 +6,7 @@ const tmp = require('tmp'); const Config = require('eslint/lib/config'); const diff = require('deep-diff').diff; const deepProperty = require('deep-property'); +const slash = require('slash'); const shell = require('shelljs'); const Handlebars = require('handlebars'); const diffTemplatePath = require.resolve('./diff-template.md'); @@ -240,7 +241,7 @@ ConfigDiff.prototype.writeDiff = function(options) { } else if (/^https?:/.test(configPath)) { return configPath; } - return path.relative(path.dirname(renderOutputPath), configPath); + return slash(path.relative(path.dirname(renderOutputPath), configPath)); } const templateData = { From 9d82fdac3f6c5f5f92850c1d45df7cfecb64c7a6 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Fri, 5 Feb 2016 09:46:36 -0700 Subject: [PATCH 37/71] Add slash package --- packages/eslint-config-hudl/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index 3683688c9b..775ae94b7c 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -85,6 +85,7 @@ "shelljs": "^0.5.3", "sinon": "^1.17.3", "sinon-chai": "^2.8.0", + "slash": "^1.0.0", "tape": "^4.2.2", "tmp": "0.0.28" }, From 95999e630639251442f1f50b96c9f8e516251d8a Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Fri, 5 Feb 2016 10:08:35 -0700 Subject: [PATCH 38/71] Fix original tests --- packages/eslint-config-hudl/test/original/test-base.js | 6 +++--- .../eslint-config-hudl/test/original/test-react-order.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/eslint-config-hudl/test/original/test-base.js b/packages/eslint-config-hudl/test/original/test-base.js index 5ac9a05790..d066f8212d 100644 --- a/packages/eslint-config-hudl/test/original/test-base.js +++ b/packages/eslint-config-hudl/test/original/test-base.js @@ -3,15 +3,15 @@ import path from 'path'; import test from 'tape'; const files = { - base: require('../base'), + base: require('../../base'), }; -fs.readdirSync(path.join(__dirname, '../rules')).forEach(name => { +fs.readdirSync(path.join(__dirname, '../../rules')).forEach(name => { if (name === 'react.js') { return; } - files[name] = require(`../rules/${name}`); + files[name] = require(`../../rules/${name}`); }); Object.keys(files).forEach(name => { diff --git a/packages/eslint-config-hudl/test/original/test-react-order.js b/packages/eslint-config-hudl/test/original/test-react-order.js index 6b6847b1fa..556c587f9f 100644 --- a/packages/eslint-config-hudl/test/original/test-react-order.js +++ b/packages/eslint-config-hudl/test/original/test-react-order.js @@ -1,7 +1,7 @@ import test from 'tape'; import { CLIEngine } from 'eslint'; -import eslintrc from '../'; -import reactRules from '../rules/react'; +import eslintrc from '../../'; +import reactRules from '../../rules/react'; const cli = new CLIEngine({ useEslintrc: false, @@ -69,7 +69,8 @@ test('validate react prop order', t => { t.equal(result.messages[0].ruleId, 'react/sort-comp', 'fails due to sort'); }); - t.test('order: when random method after lifecycle methods', t => { + // Skipping because our rules differ + t.skip('order: when random method after lifecycle methods', t => { t.plan(2); const result = lint(wrapComponent(` componentWillMount() {} From 516686f735b589a7bbbc6ad568f5259a4661be00 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Mon, 8 Feb 2016 10:06:55 -0700 Subject: [PATCH 39/71] Add babel-lint parser for react config - Add babel-lint parser for only react (default) config - Add some cross-links in docs --- linters/.eslintrc | 2 + packages/eslint-config-hudl/README.md | 17 +++-- .../comparisons/before-packaging-refactor.md | 2 - .../docs/comparisons/with-airbnb-master.md | 3 +- packages/eslint-config-hudl/package.json | 1 + packages/eslint-config-hudl/rules/react.js | 1 + .../test/__specs__/config-specs.js | 32 +++++++++ .../__specs__/fixtures/static-props/test.jsx | 68 +++++++++++++++++++ 8 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 packages/eslint-config-hudl/test/__specs__/config-specs.js create mode 100644 packages/eslint-config-hudl/test/__specs__/fixtures/static-props/test.jsx diff --git a/linters/.eslintrc b/linters/.eslintrc index 9e203a5473..5b840a5f2d 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -1,5 +1,7 @@ // Use this file as a starting point for your project's .eslintrc. // Copy this file, and add rule overrides as needed. +// See more info at https://github.com/hudl/javascript/tree/master/packages/eslint-config-hudl { + "root": true, "extends": "airbnb" } diff --git a/packages/eslint-config-hudl/README.md b/packages/eslint-config-hudl/README.md index 33a01b22bb..5886d459b5 100644 --- a/packages/eslint-config-hudl/README.md +++ b/packages/eslint-config-hudl/README.md @@ -9,31 +9,32 @@ the Airbnb config, take a look at the [comparison docs](docs/comparisons/). We export three ESLint configurations for your usage. +See [Hudl's Javascript styleguide](https://github.com/hudl/javascript) and +the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) +for more information on using config plugins. + ### eslint-config-hudl Our default export contains all of our ESLint rules, including EcmaScript 6+ and React. It requires `eslint` and `eslint-plugin-react`. -1. `npm install --save-dev eslint-config-hudl eslint-plugin-react eslint --registry=http://npm.thorhudl.com` -2. add `"extends": "hudl"` to your .eslintrc +1. `npm install --save-dev eslint-config-hudl eslint-plugin-react babel-eslint eslint --registry=http://npm.thorhudl.com` +2. Add `"extends": "hudl"` to [your .eslintrc][eslintrc] ### eslint-config-hudl/base Lints ES6+ but does not lint React. Requires `eslint`. 1. `npm install --save-dev eslint-config-hudl eslint --registry=http://npm.thorhudl.com` -2. add `"extends": "hudl/base"` to your .eslintrc +2. Add `"extends": "hudl/base"` to [your .eslintrc][eslintrc] ### eslint-config-hudl/legacy Lints ES5 and below. Only requires `eslint`. 1. `npm install --save-dev eslint-config-hudl eslint --registry=http://npm.thorhudl.com` -2. add `"extends": "hudl/legacy"` to your .eslintrc +2. Add `"extends": "hudl/legacy"` to [your .eslintrc][eslintrc] -See [Hudl's Javascript styleguide](https://github.com/hudl/javascript) and -the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) -for more information. ## Improving this config @@ -44,3 +45,5 @@ programming to structure our README as test cases for our .eslintrc? You can run tests with `npm test`. You can make sure this module lints with itself using `npm run lint`. + +[eslintrc]: ../../linters/.eslintrc diff --git a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md index 0ad68cc6d3..6336ce6d36 100644 --- a/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md +++ b/packages/eslint-config-hudl/docs/comparisons/before-packaging-refactor.md @@ -34,8 +34,6 @@ should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-r ### Settings (non-rules) -- parser - - ["babel-eslint"] - env.amd - [false] - env.mocha diff --git a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md index 3ffbb7697c..71667f2476 100644 --- a/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md +++ b/packages/eslint-config-hudl/docs/comparisons/with-airbnb-master.md @@ -33,8 +33,9 @@ upstream changes that haven't been merged yet. Any differences listed here that should be added to the list in [the diff task](../../tasks/docs/diffs/diffs-to-run.js) to remove them from here. ### Settings (non-rules) -_None_ +- parser + - ["babel-eslint"] ### Rules diff --git a/packages/eslint-config-hudl/package.json b/packages/eslint-config-hudl/package.json index 775ae94b7c..a1356369c5 100644 --- a/packages/eslint-config-hudl/package.json +++ b/packages/eslint-config-hudl/package.json @@ -59,6 +59,7 @@ } }, "devDependencies": { + "babel-eslint": "^5.0.0-beta9", "babel-tape-runner": "1.2.0", "big-object-diff": "^0.7.0", "chai": "^3.5.0", diff --git a/packages/eslint-config-hudl/rules/react.js b/packages/eslint-config-hudl/rules/react.js index 211ca01df0..097b9e852b 100644 --- a/packages/eslint-config-hudl/rules/react.js +++ b/packages/eslint-config-hudl/rules/react.js @@ -1,4 +1,5 @@ module.exports = { + 'parser': 'babel-eslint', 'plugins': [ 'react', ], diff --git a/packages/eslint-config-hudl/test/__specs__/config-specs.js b/packages/eslint-config-hudl/test/__specs__/config-specs.js new file mode 100644 index 0000000000..7c76e5e732 --- /dev/null +++ b/packages/eslint-config-hudl/test/__specs__/config-specs.js @@ -0,0 +1,32 @@ +const path = require('path'); +const CLIEngine = require('eslint').CLIEngine; +const defaultConfig = require('../..'); +const baseConfig = require('../../base'); +const legacyConfig = require('../../legacy'); + +describe.only('configs', function() { + function lintDirectory(directory, config, errorCount, warningCount) { + const cli = new CLIEngine({ + extensions: ['.js', '.jsx'], + useEslintrc: false, + baseConfig: config, + }); + const report = cli.executeOnFiles([directory]); + + expect(report).to.have.property('errorCount', errorCount); + expect(report).to.have.property('warningCount', warningCount); + } + + describe('should handle static property declarations', function() { + const directory = path.resolve(__dirname, 'fixtures/static-props'); + it('as valid using default (hudl) config', function() { + lintDirectory(directory, defaultConfig, 0, 0); + }); + it('with errors using base (hudl/base) config', function() { + lintDirectory(directory, baseConfig, 1, 0); + }); + it('with errors using legacy (hudl/legacy) config', function() { + lintDirectory(directory, legacyConfig, 1, 0); + }); + }); +}); diff --git a/packages/eslint-config-hudl/test/__specs__/fixtures/static-props/test.jsx b/packages/eslint-config-hudl/test/__specs__/fixtures/static-props/test.jsx new file mode 100644 index 0000000000..3421d848f6 --- /dev/null +++ b/packages/eslint-config-hudl/test/__specs__/fixtures/static-props/test.jsx @@ -0,0 +1,68 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import React, { Component, PropTypes } from 'react'; +import emptyFunction from 'fbjs/lib/emptyFunction'; +import s from './App.scss'; +import Header from '../Header'; +import Feedback from '../Feedback'; +import Footer from '../Footer'; + +class App extends Component { + + static propTypes = { + context: PropTypes.shape({ + insertCss: PropTypes.func, + onSetTitle: PropTypes.func, + onSetMeta: PropTypes.func, + onPageNotFound: PropTypes.func, + }), + children: PropTypes.element.isRequired, + error: PropTypes.object, + }; + + static childContextTypes = { + insertCss: PropTypes.func.isRequired, + onSetTitle: PropTypes.func.isRequired, + onSetMeta: PropTypes.func.isRequired, + onPageNotFound: PropTypes.func.isRequired, + }; + + getChildContext() { + const context = this.props.context; + return { + insertCss: context.insertCss || emptyFunction, + onSetTitle: context.onSetTitle || emptyFunction, + onSetMeta: context.onSetMeta || emptyFunction, + onPageNotFound: context.onPageNotFound || emptyFunction, + }; + } + + componentWillMount() { + this.removeCss = this.props.context.insertCss(s); + } + + componentWillUnmount() { + this.removeCss(); + } + + render() { + return !this.props.error ? ( +
+
+ {this.props.children} + +
+
+ ) : this.props.children; + } + +} + +export default App; From c136dfcd995da7124a51c06e869c1ea5b0143550 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Mon, 8 Feb 2016 10:09:21 -0700 Subject: [PATCH 40/71] Re-enable all tests --- packages/eslint-config-hudl/test/__specs__/config-specs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-config-hudl/test/__specs__/config-specs.js b/packages/eslint-config-hudl/test/__specs__/config-specs.js index 7c76e5e732..91b70b84f3 100644 --- a/packages/eslint-config-hudl/test/__specs__/config-specs.js +++ b/packages/eslint-config-hudl/test/__specs__/config-specs.js @@ -4,7 +4,7 @@ const defaultConfig = require('../..'); const baseConfig = require('../../base'); const legacyConfig = require('../../legacy'); -describe.only('configs', function() { +describe('configs', function() { function lintDirectory(directory, config, errorCount, warningCount) { const cli = new CLIEngine({ extensions: ['.js', '.jsx'], From 1d53dfc711b824a9dba4a145a22f0fde64385261 Mon Sep 17 00:00:00 2001 From: Lyle Shearer Date: Mon, 8 Feb 2016 12:17:48 -0700 Subject: [PATCH 41/71] Revert style guide changes and fix linters/README --- README.md | 521 ++++++-------------------- es5/README.md | 3 +- linters/.eslintrc | 1 - linters/README.md | 11 +- packages/eslint-config-hudl/README.md | 2 +- react/README.md | 233 ++++-------- 6 files changed, 187 insertions(+), 584 deletions(-) diff --git a/README.md b/README.md index 5aa34475cb..584d3bf227 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ Forked from [AirBNB's style guide](https://github.com/airbnb/javascript) -Other Style Guides - - [ES5](es5/) - - [React](react/) +[For the ES5-only guide click here](es5/). ## Table of Contents @@ -43,7 +41,7 @@ Other Style Guides 1. [In the Wild](#in-the-wild) 1. [Translation](#translation) 1. [The JavaScript Style Guide Guide](#the-javascript-style-guide-guide) - 1. [Chat With Us About JavaScript](#chat-with-us-about-javascript) + 1. [Chat With Us About Javascript](#chat-with-us-about-javascript) 1. [Contributors](#contributors) 1. [License](#license) @@ -84,9 +82,9 @@ Other Style Guides ## References - - [2.1](#2.1) Use `const` for all of your references; avoid using `var`. eslint: [`prefer-const`](http://eslint.org/docs/rules/prefer-const.html), [`no-const-assign`](http://eslint.org/docs/rules/no-const-assign.html) + - [2.1](#2.1) Use `const` for all of your references; avoid using `var`. - > Why? This ensures that you can't reassign your references, which can lead to bugs and difficult to comprehend code. + > Why? This ensures that you can't reassign your references (mutation), which can lead to bugs and difficult to comprehend code. ```javascript // bad @@ -98,7 +96,7 @@ Other Style Guides const b = 2; ``` - - [2.2](#2.2) If you must reassign references, use `let` instead of `var`. eslint: [`no-var`](http://eslint.org/docs/rules/no-var.html) jscs: [`disallowVar`](http://jscs.info/rule/disallowVar) + - [2.2](#2.2) If you must mutate references, use `let` instead of `var`. > Why? `let` is block-scoped rather than function-scoped like `var`. @@ -132,7 +130,7 @@ Other Style Guides ## Objects - - [3.1](#3.1) Use the literal syntax for object creation. eslint: [`no-new-object`](http://eslint.org/docs/rules/no-new-object.html) + - [3.1](#3.1) Use the literal syntax for object creation. ```javascript // bad @@ -142,7 +140,7 @@ Other Style Guides const item = {}; ``` - - [3.2](#3.2) If your code will be executed in browsers in script context, don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61). It’s OK to use them in ES6 modules and server-side code. jscs: [`disallowIdentiferNames`](http://jscs.info/rule/disallowIdentifierNames) + - [3.2](#3.2) If your code will be executed in browsers in script context, don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61). It’s OK to use them in ES6 modules and server-side code. ```javascript // bad @@ -158,7 +156,7 @@ Other Style Guides }; ``` - - [3.3](#3.3) Use readable synonyms in place of reserved words. jscs: [`disallowIdentiferNames`](http://jscs.info/rule/disallowIdentifierNames) + - [3.3](#3.3) Use readable synonyms in place of reserved words. ```javascript // bad @@ -204,7 +202,7 @@ Other Style Guides ``` - - [3.5](#3.5) Use object method shorthand. eslint: [`object-shorthand`](http://eslint.org/docs/rules/object-shorthand.html) jscs: [`requireEnhancedObjectLiterals`](http://jscs.info/rule/requireEnhancedObjectLiterals) + - [3.5](#3.5) Use object method shorthand. ```javascript // bad @@ -227,7 +225,7 @@ Other Style Guides ``` - - [3.6](#3.6) Use property value shorthand. eslint: [`object-shorthand`](http://eslint.org/docs/rules/object-shorthand.html) jscs: [`requireEnhancedObjectLiterals`](http://jscs.info/rule/requireEnhancedObjectLiterals) + - [3.6](#3.6) Use property value shorthand. > Why? It is shorter to write and descriptive. @@ -274,31 +272,11 @@ Other Style Guides }; ``` - - [3.8](#3.8) Only quote properties that are invalid identifiers. eslint: [`quote-props`](http://eslint.org/docs/rules/quote-props.html) jscs: [`disallowQuotedKeysInObjects`](http://jscs.info/rule/disallowQuotedKeysInObjects) - - > Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines. - - ```javascript - // bad - const bad = { - 'foo': 3, - 'bar': 4, - 'data-blah': 5, - }; - - // good - const good = { - foo: 3, - bar: 4, - 'data-blah': 5, - }; - ``` - **[⬆ back to top](#table-of-contents)** ## Arrays - - [4.1](#4.1) Use the literal syntax for array creation. eslint: [`no-array-constructor`](http://eslint.org/docs/rules/no-array-constructor.html) + - [4.1](#4.1) Use the literal syntax for array creation. ```javascript // bad @@ -347,7 +325,7 @@ Other Style Guides ## Destructuring - - [5.1](#5.1) Use object destructuring when accessing and using multiple properties of an object. jscs: [`requireObjectDestructuring`](http://jscs.info/rule/requireObjectDestructuring) + - [5.1](#5.1) Use object destructuring when accessing and using multiple properties of an object. > Why? Destructuring saves you from creating temporary references for those properties. @@ -361,8 +339,8 @@ Other Style Guides } // good - function getFullName(user) { - const { firstName, lastName } = user; + function getFullName(obj) { + const { firstName, lastName } = obj; return `${firstName} ${lastName}`; } @@ -372,7 +350,7 @@ Other Style Guides } ``` - - [5.2](#5.2) Use array destructuring. jscs: [`requireArrayDestructuring`](http://jscs.info/rule/requireArrayDestructuring) + - [5.2](#5.2) Use array destructuring. ```javascript const arr = [1, 2, 3, 4]; @@ -414,7 +392,7 @@ Other Style Guides ## Strings - - [6.1](#6.1) Use single quotes `''` for strings. eslint: [`quotes`](http://eslint.org/docs/rules/quotes.html) jscs: [`validateQuoteMarks`](http://jscs.info/rule/validateQuoteMarks) + - [6.1](#6.1) Use single quotes `''` for strings. ```javascript // bad @@ -424,7 +402,7 @@ Other Style Guides const name = 'Capt. Janeway'; ``` - - [6.2](#6.2) Strings that cause the line to go over 100 characters should be written across multiple lines using string concatenation. + - [6.2](#6.2) Strings longer than 80 characters should be written across multiple lines using string concatenation. - [6.3](#6.3) 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). ```javascript @@ -444,7 +422,7 @@ Other Style Guides ``` - - [6.4](#6.4) When programmatically building up strings, use template strings instead of concatenation. eslint: [`prefer-template`](http://eslint.org/docs/rules/prefer-template.html) jscs: [`requireTemplateStrings`](http://jscs.info/rule/requireTemplateStrings) + - [6.4](#6.4) When programmatically building up strings, use template strings instead of concatenation. > Why? Template strings give you a readable, concise syntax with proper newlines and string interpolation features. @@ -464,14 +442,13 @@ Other Style Guides return `How are you, ${name}?`; } ``` - - [6.5](#6.5) Never use `eval()` on a string, it opens too many vulnerabilities. **[⬆ back to top](#table-of-contents)** ## Functions - - [7.1](#7.1) Use function declarations instead of function expressions. jscs: [`requireFunctionDeclarations`](http://jscs.info/rule/requireFunctionDeclarations) + - [7.1](#7.1) Use function declarations instead of function expressions. > Why? Function declarations are named, so they're easier to identify in call stacks. Also, the whole body of a function declaration is hoisted, whereas only the reference of a function expression is hoisted. This rule makes it possible to always use [Arrow Functions](#arrow-functions) in place of function expressions. @@ -485,19 +462,16 @@ Other Style Guides } ``` - - [7.2](#7.2) Immediately invoked function expressions: eslint: [`wrap-iife`](http://eslint.org/docs/rules/wrap-iife.html) jscs: [`requireParenthesesAroundIIFE`](http://jscs.info/rule/requireParenthesesAroundIIFE) - - > 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. + - [7.2](#7.2) Function expressions: ```javascript // immediately-invoked function expression (IIFE) - (function () { + (() => { console.log('Welcome to the Internet. Please follow me.'); - }()); + })(); ``` - - [7.3](#7.3) 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`](http://eslint.org/docs/rules/no-loop-func.html) - + - [7.3](#7.3) 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. - [7.4](#7.4) **Note:** ECMA-262 defines a `block` as a list of statements. A function declaration is not a statement. [Read ECMA-262's note on this issue](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97). ```javascript @@ -576,7 +550,7 @@ Other Style Guides } ``` - - [7.8](#7.8) Avoid side effects with default parameters. + - [7.8](#7.8) Avoid side effects with default parameters > Why? They are confusing to reason about. @@ -592,21 +566,7 @@ Other Style Guides count(); // 3 ``` - - [7.9](#7.9) Always put default parameters last. - - ```javascript - // bad - function handleThings(opts = {}, name) { - // ... - } - - // good - function handleThings(name, opts = {}) { - // ... - } - ``` - - - [7.10](#7.10) Never use the Function constructor to create a new function. +- [7.9](#7.9) Never use the Function constructor to create a new function. > Why? Creating a function in this way evaluates a string similarly to eval(), which opens vulnerabilities. @@ -618,65 +578,11 @@ Other Style Guides var subtract = Function('a', 'b', 'return a - b'); ``` - - [7.11](#7.11) Spacing in a function signature. - - > Why? Consistency is good, and you shouldn’t have to add or remove a space when adding or removing a name. - - ```javascript - // bad - const f = function(){}; - const g = function (){}; - const h = function() {}; - - // good - const x = function () {}; - const y = function a() {}; - ``` - - - [7.12](#7.12) Never mutate parameters. eslint: [`no-param-reassign`](http://eslint.org/docs/rules/no-param-reassign.html) - - > Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller. - - ```javascript - // bad - function f1(obj) { - obj.key = 1; - }; - - // good - function f2(obj) { - const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; - }; - ``` - - - [7.13](#7.13) Never reassign parameters. eslint: [`no-param-reassign`](http://eslint.org/docs/rules/no-param-reassign.html) - - > Why? Reassigning parameters can lead to unexpected behavior, especially when accessing the `arguments` object. It can also cause optimization issues, especially in V8. - - ```javascript - // bad - function f1(a) { - a = 1; - } - - function f2(a) { - if (!a) { a = 1; } - } - - // good - function f3(a) { - const b = a || 1; - } - - function f4(a = 1) { - } - ``` - **[⬆ back to top](#table-of-contents)** ## Arrow Functions - - [8.1](#8.1) When you must use function expressions (as when passing an anonymous function), use arrow function notation. eslint: [`prefer-arrow-callback`](http://eslint.org/docs/rules/prefer-arrow-callback.html), [`arrow-spacing`](http://eslint.org/docs/rules/arrow-spacing.html) jscs: [`requireArrowFunctions`](http://jscs.info/rule/requireArrowFunctions) + - [8.1](#8.1) When you must use function expressions (as when passing an anonymous function), use arrow function notation. > 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. @@ -685,87 +591,29 @@ Other Style Guides ```javascript // bad [1, 2, 3].map(function (x) { - const y = x + 1; - return x * y; + return x * x; }); // good [1, 2, 3].map((x) => { - const y = x + 1; - return x * y; + return x * x; }); ``` - - [8.2](#8.2) If the function body consists of a single expression, omit the braces and use the implicit return. Otherwise, keep the braces and use a `return` statement. eslint: [`arrow-parens`](http://eslint.org/docs/rules/arrow-parens.html), [`arrow-body-style`](http://eslint.org/docs/rules/arrow-body-style.html) jscs: [`disallowParenthesesAroundArrowParam`](http://jscs.info/rule/disallowParenthesesAroundArrowParam), [`requireShorthandArrowFunctions`](http://jscs.info/rule/requireShorthandArrowFunctions) + - [8.2](#8.2) If the function body fits on one line and there is only a single argument, feel free to omit the braces and parentheses, and use the implicit return. Otherwise, add the parentheses, braces, and use a `return` statement. > Why? Syntactic sugar. It reads well when multiple functions are chained together. > Why not? If you plan on returning an object. ```javascript - // good - [1, 2, 3].map(number => `A string containing the ${number}.`); - - // bad - [1, 2, 3].map(number => { - const nextNumber = number + 1; - `A string containing the ${nextNumber}.`; - }); - - // good - [1, 2, 3].map(number => { - const nextNumber = number + 1; - return `A string containing the ${nextNumber}.`; - }); - ``` - - - [8.3](#8.3) In case the expression spans over multiple lines, wrap it in parentheses for better readability. - - > Why? It shows clearly where the function starts and ends. - - ```js - // bad - [1, 2, 3].map(number => 'As time went by, the string containing the ' + - `${number} became much longer. So we needed to break it over multiple ` + - 'lines.' - ); - - // good - [1, 2, 3].map(number => ( - `As time went by, the string containing the ${number} became much ` + - 'longer. So we needed to break it over multiple lines.' - )); - ``` - - - - [8.4](#8.4) If your function takes a single argument and doesn’t use braces, omit the parentheses. Otherwise, always include parentheses around arguments. eslint: [`arrow-parens`](http://eslint.org/docs/rules/arrow-parens.html) jscs: [`disallowParenthesesAroundArrowParam`](http://jscs.info/rule/disallowParenthesesAroundArrowParam) - - > Why? Less visual clutter. - - ```js - // bad - [1, 2, 3].map((x) => x * x); - // good [1, 2, 3].map(x => x * x); // good - [1, 2, 3].map(number => ( - `A long string with the ${number}. It’s so long that we’ve broken it ` + - 'over multiple lines!' - )); - - // bad - [1, 2, 3].map(x => { - const y = x + 1; - return x * y; - }); - - // good - [1, 2, 3].map((x) => { - const y = x + 1; - return x * y; - }); + [1, 2, 3].reduce((total, n) => { + return total + n; + }, 0); ``` **[⬆ back to top](#table-of-contents)** @@ -934,7 +782,7 @@ Other Style Guides ## Iterators and Generators - - [11.1](#11.1) Don't use iterators. Prefer JavaScript's higher-order functions like `map()` and `reduce()` instead of loops like `for-of`. eslint: [`no-iterator`](http://eslint.org/docs/rules/no-iterator.html) + - [11.1](#11.1) Don't use iterators. Prefer JavaScript's higher-order functions like `map()` and `reduce()` instead of loops like `for-of`. > Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side-effects. @@ -951,7 +799,7 @@ Other Style Guides // good let sum = 0; - numbers.forEach(num => sum += num); + numbers.forEach((num) => sum += num); sum === 15; // best (use the functional force) @@ -968,7 +816,7 @@ Other Style Guides ## Properties - - [12.1](#12.1) Use dot notation when accessing properties. eslint: [`dot-notation`](http://eslint.org/docs/rules/dot-notation.html) jscs: [`requireDotNotation`](http://jscs.info/rule/requireDotNotation) + - [12.1](#12.1) Use dot notation when accessing properties. ```javascript const luke = { @@ -1013,7 +861,7 @@ Other Style Guides const superPower = new SuperPower(); ``` - - [13.2](#13.2) Use one `const` declaration per variable. eslint: [`one-var`](http://eslint.org/docs/rules/one-var.html) jscs: [`disallowMultipleVarDecl`](http://jscs.info/rule/disallowMultipleVarDecl) + - [13.2](#13.2) Use one `const` declaration per variable. > 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. @@ -1065,36 +913,45 @@ Other Style Guides > Why? `let` and `const` are block scoped and not function scoped. ```javascript - // bad - unnecessary function call - function checkName(hasName) { - const name = getName(); + // good + function() { + test(); + console.log('doing stuff..'); - if (hasName === 'test') { - return false; - } + //..other stuff.. + + const name = getName(); if (name === 'test') { - this.setName(''); return false; } return name; } - // good - function checkName(hasName) { - if (hasName === 'test') { + // bad - unnecessary function call + function(hasName) { + const name = getName(); + + if (!hasName) { return false; } - const name = getName(); + this.setFirstName(name); - if (name === 'test') { - this.setName(''); + return true; + } + + // good + function(hasName) { + if (!hasName) { return false; } - return name; + const name = getName(); + this.setFirstName(name); + + return true; } ``` @@ -1121,7 +978,7 @@ Other Style Guides var declaredButNotAssigned = true; } - // the interpreter is hoisting the variable + // The interpreter is hoisting the variable // declaration to the top of the scope, // which means our example could be rewritten as: function example() { @@ -1192,15 +1049,14 @@ 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/). + - 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/). **[⬆ back to top](#table-of-contents)** ## Comparison Operators & Equality - - [15.1](#15.1) Use `===` and `!==` over `==` and `!=`. eslint: [`eqeqeq`](http://eslint.org/docs/rules/eqeqeq.html) - + - [15.1](#15.1) Use `===` and `!==` over `==` and `!=`. - [15.2](#15.2) Conditional statements such as the `if` statement evaluate their expression using coercion with the `ToBoolean` abstract method and always follow these simple rules: + **Objects** evaluate to **true** @@ -1211,9 +1067,9 @@ Other Style Guides + **Strings** evaluate to **false** if an empty string `''`, otherwise **true** ```javascript - if ([0] && []) { + if ([0]) { // true - // an array (even an empty one) is an object, objects will evaluate to true + // An array is an object, objects evaluate to true } ``` @@ -1264,16 +1120,16 @@ Other Style Guides } // bad - function foo() { return false; } + function() { return false; } // good - function bar() { + function() { return false; } ``` - [16.2](#16.2) 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`](http://eslint.org/docs/rules/brace-style.html) jscs: [`disallowNewlineBeforeBlockStatements`](http://jscs.info/rule/disallowNewlineBeforeBlockStatements) + `if` block's closing brace. ```javascript // bad @@ -1332,7 +1188,7 @@ Other Style Guides } ``` - - [17.2](#17.2) Use `//` for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment unless it's on the first line of a block. + - [17.2](#17.2) Use `//` for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment. ```javascript // bad @@ -1360,14 +1216,6 @@ Other Style Guides return type; } - - // also good - function getType() { - // set the default type to 'no type' - const type = this._type || 'no type'; - - return type; - } ``` - [17.3](#17.3) Prefixing your comments with `FIXME` or `TODO` helps other developers quickly understand if you're pointing out a problem that needs to be revisited, or if you're suggesting a solution to the problem that needs to be implemented. These are different than regular comments because they are actionable. The actions are `FIXME -- need to figure this out` or `TODO -- need to implement`. @@ -1375,10 +1223,8 @@ Other Style Guides - [17.4](#17.4) Use `// FIXME:` to annotate problems. ```javascript - class Calculator extends Abacus { + class Calculator { constructor() { - super(); - // FIXME: shouldn't use a global here total = 0; } @@ -1388,10 +1234,8 @@ Other Style Guides - [17.5](#17.5) Use `// TODO:` to annotate solutions to problems. ```javascript - class Calculator extends Abacus { + class Calculator { constructor() { - super(); - // TODO: total should be configurable by an options param this.total = 0; } @@ -1403,26 +1247,26 @@ Other Style Guides ## Whitespace - - [18.1](#18.1) Use soft tabs set to 2 spaces. eslint: [`indent`](http://eslint.org/docs/rules/indent.html) jscs: [`validateIndentation`](http://jscs.info/rule/validateIndentation) + - [18.1](#18.1) Use soft tabs set to 2 spaces. ```javascript // bad - function foo() { + function() { ∙∙∙∙const name; } // bad - function bar() { + function() { ∙const name; } // good - function baz() { + function() { ∙∙const name; } ``` - - [18.2](#18.2) Place 1 space before the leading brace. eslint: [`space-before-blocks`](http://eslint.org/docs/rules/space-before-blocks.html) jscs: [`requireSpaceBeforeBlockStatements`](http://jscs.info/rule/requireSpaceBeforeBlockStatements) + - [18.2](#18.2) Place 1 space before the leading brace. ```javascript // bad @@ -1448,7 +1292,7 @@ Other Style Guides }); ``` - - [18.3](#18.3) 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: [`space-after-keywords`](http://eslint.org/docs/rules/space-after-keywords.html), [`space-before-keywords`](http://eslint.org/docs/rules/space-before-keywords.html) jscs: [`requireSpaceAfterKeywords`](http://jscs.info/rule/requireSpaceAfterKeywords) + - [18.3](#18.3) Place 1 space before the opening parenthesis in control statements (`if`, `while` etc.). Place no space before the argument list in function calls and declarations. ```javascript // bad @@ -1472,7 +1316,7 @@ Other Style Guides } ``` - - [18.4](#18.4) Set off operators with spaces. eslint: [`space-infix-ops`](http://eslint.org/docs/rules/space-infix-ops.html) jscs: [`requireSpaceBeforeBinaryOperators`](http://jscs.info/rule/requireSpaceBeforeBinaryOperators), [`requireSpaceAfterBinaryOperators`](http://jscs.info/rule/requireSpaceAfterBinaryOperators) + - [18.4](#18.4) Set off operators with spaces. ```javascript // bad @@ -1506,7 +1350,7 @@ Other Style Guides })(this);↵ ``` - - [18.6](#18.6) Use indentation when making long method chains. Use a leading dot, which + - [18.5](#18.5) Use indentation when making long method chains. Use a leading dot, which emphasizes that the line is a method call, not a new statement. ```javascript @@ -1546,7 +1390,7 @@ Other Style Guides .call(tron.led); ``` - - [18.7](#18.7) Leave a blank line after blocks and before the next statement. jscs: [`requirePaddingNewLinesAfterBlocks`](http://jscs.info/rule/requirePaddingNewLinesAfterBlocks) + - [18.6](#18.6) Leave a blank line after blocks and before the next statement. ```javascript // bad @@ -1603,114 +1447,12 @@ Other Style Guides return arr; ``` - - [18.8](#18.8) Do not pad your blocks with blank lines. eslint: [`padded-blocks`](http://eslint.org/docs/rules/padded-blocks.html) jscs: [`disallowPaddingNewlinesInBlocks`](http://jscs.info/rule/disallowPaddingNewlinesInBlocks) - - ```javascript - // bad - function bar() { - - console.log(foo); - - } - - // also bad - if (baz) { - - console.log(qux); - } else { - console.log(foo); - - } - - // good - function bar() { - console.log(foo); - } - - // good - if (baz) { - console.log(qux); - } else { - console.log(foo); - } - ``` - - - [18.9](#18.9) Do not add spaces inside parentheses. eslint: [`space-in-parens`](http://eslint.org/docs/rules/space-in-parens.html) jscs: [`disallowSpacesInsideParentheses`](http://jscs.info/rule/disallowSpacesInsideParentheses) - - ```javascript - // bad - function bar( foo ) { - return foo; - } - - // good - function bar(foo) { - return foo; - } - - // bad - if ( foo ) { - console.log(foo); - } - - // good - if (foo) { - console.log(foo); - } - ``` - - - [18.10](#18.10) Do not add spaces inside brackets. eslint: [`array-bracket-spacing`](http://eslint.org/docs/rules/array-bracket-spacing.html) jscs: [`disallowSpacesInsideArrayBrackets`](http://jscs.info/rule/disallowSpacesInsideArrayBrackets) - - ```javascript - // bad - const foo = [ 1, 2, 3 ]; - console.log(foo[ 0 ]); - - // good - const foo = [1, 2, 3]; - console.log(foo[0]); - ``` - - - [18.11](#18.11) Add spaces inside curly braces. eslint: [`object-curly-spacing`](http://eslint.org/docs/rules/object-curly-spacing.html) jscs: [`disallowSpacesInsideObjectBrackets`](http://jscs.info/rule/disallowSpacesInsideObjectBrackets) - - ```javascript - // bad - const foo = {clark: 'kent'}; - - // good - const foo = { clark: 'kent' }; - ``` - - - [18.12](#18.12) Avoid having lines of code that are longer than 100 characters (including whitespace). eslint: [`max-len`](http://eslint.org/docs/rules/max-len.html) jscs: [`maximumLineLength`](http://jscs.info/rule/maximumLineLength) - - > Why? This ensures readability and maintainability. - - ```javascript - // bad - const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. Whatever wizard constrains a helpful ally. The counterpart ascends!'; - - // bad - $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); - - // good - const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. ' + - 'Whatever wizard constrains a helpful ally. The counterpart ascends!'; - - // good - $.ajax({ - method: 'POST', - url: 'https://airbnb.com/', - data: { name: 'John' }, - }) - .done(() => console.log('Congratulations!')) - .fail(() => console.log('You have failed this city.')); - ``` **[⬆ back to top](#table-of-contents)** ## Commas - - [19.1](#19.1) Leading commas: **Nope.** eslint: [`comma-style`](http://eslint.org/docs/rules/comma-style.html) jscs: [`requireCommaBeforeLineBreak`](http://jscs.info/rule/requireCommaBeforeLineBreak) + - [19.1](#19.1) Leading commas: **Nope.** ```javascript // bad @@ -1744,7 +1486,7 @@ Other Style Guides }; ``` - - [19.2](#19.2) Additional trailing comma: **Yup.** eslint: [`comma-dangle`](http://eslint.org/docs/rules/comma-dangle.html) jscs: [`requireTrailingComma`](http://jscs.info/rule/requireTrailingComma) + - [19.2](#19.2) Additional trailing comma: **Yup.** > 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. @@ -1755,14 +1497,14 @@ Other Style Guides - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb graph', 'modern nursing'] - }; + } // good - git diff with trailing comma const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], - }; + } // bad const hero = { @@ -1792,7 +1534,7 @@ Other Style Guides ## Semicolons - - [20.1](#20.1) **Yup.** eslint: [`semi`](http://eslint.org/docs/rules/semi.html) jscs: [`requireSemicolons`](http://jscs.info/rule/requireSemicolons) + - [20.1](#20.1) **Yup.** ```javascript // bad @@ -1805,16 +1547,16 @@ Other Style Guides (() => { const name = 'Skywalker'; return name; - }()); + })(); // good (guards against the function becoming an argument when two files with IIFEs are concatenated) ;(() => { const name = 'Skywalker'; return name; - }()); + })(); ``` - [Read more](http://stackoverflow.com/questions/7365172/semicolon-before-self-invoking-function/7365214%237365214). + [Read more](http://stackoverflow.com/a/7365214/1712802). **[⬆ back to top](#table-of-contents)** @@ -1834,7 +1576,7 @@ Other Style Guides const totalScore = String(this.reviewScore); ``` - - [21.3](#21.3) Numbers: Use `Number` for type casting and `parseInt` always with a radix for parsing strings. eslint: [`radix`](http://eslint.org/docs/rules/radix) + - [21.3](#21.3) Use `parseInt` for Numbers and always with a radix for type casting. ```javascript const inputValue = '4'; @@ -1870,7 +1612,7 @@ Other Style Guides const val = inputValue >> 0; ``` - - [21.5](#21.5) **Note:** Be careful when using bitshift operations. Numbers are represented as [64-bit values](http://es5.github.io/#x4.3.19), but bitshift operations always return a 32-bit integer ([source](http://es5.github.io/#x11.7)). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. [Discussion](https://github.com/airbnb/javascript/issues/109). Largest signed 32-bit Int is 2,147,483,647: + - [21.5](#21.5) **Note:** Be careful when using bitshift operations. Numbers are represented as [64-bit values](http://es5.github.io/#x4.3.19), but Bitshift operations always return a 32-bit integer ([source](http://es5.github.io/#x11.7)). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. [Discussion](https://github.com/airbnb/javascript/issues/109). Largest signed 32-bit Int is 2,147,483,647: ```javascript 2147483647 >> 0 //=> 2147483647 @@ -1912,7 +1654,7 @@ Other Style Guides } ``` - - [22.2](#22.2) Use camelCase when naming objects, functions, and instances. eslint: [`camelcase`](http://eslint.org/docs/rules/camelcase.html) jscs: [`requireCamelCaseOrUpperCaseIdentifiers`](http://jscs.info/rule/requireCamelCaseOrUpperCaseIdentifiers) + - [22.2](#22.2) Use camelCase when naming objects, functions, and instances. ```javascript // bad @@ -1925,7 +1667,7 @@ Other Style Guides function thisIsMyFunction() {} ``` - - [22.3](#22.3) Use PascalCase when naming constructors or classes. eslint: [`new-cap`](http://eslint.org/docs/rules/new-cap.html) jscs: [`requireCapitalizedConstructors`](http://jscs.info/rule/requireCapitalizedConstructors) + - [22.3](#22.3) Use PascalCase when naming constructors or classes. ```javascript // bad @@ -1949,7 +1691,7 @@ Other Style Guides }); ``` - - [22.4](#22.4) Use a leading underscore `_` when naming private properties. eslint: [`no-underscore-dangle`](http://eslint.org/docs/rules/no-underscore-dangle.html) jscs: [`disallowDanglingUnderscores`](http://jscs.info/rule/disallowDanglingUnderscores) + - [22.4](#22.4) Use a leading underscore `_` when naming private properties. ```javascript // bad @@ -1960,7 +1702,7 @@ Other Style Guides this._firstName = 'Panda'; ``` - - [22.5](#22.5) Don't save references to `this`. Use arrow functions or Function#bind. jscs: [`disallowNodeTypes`](http://jscs.info/rule/disallowNodeTypes) + - [22.5](#22.5) Don't save references to `this`. Use arrow functions or Function#bind. ```javascript // bad @@ -1988,7 +1730,6 @@ Other Style Guides ``` - [22.6](#22.6) If your file exports a single class, your filename should be exactly the name of the class. - ```javascript // file contents class CheckBox { @@ -2096,7 +1837,7 @@ Other Style Guides ... - $(this).on('listingUpdated', (e, listingId) => { + $(this).on('listingUpdated', function(e, listingId) { // do something with listingId }); ``` @@ -2109,7 +1850,7 @@ Other Style Guides ... - $(this).on('listingUpdated', (e, data) => { + $(this).on('listingUpdated', function(e, data) { // do something with data.listingId }); ``` @@ -2119,7 +1860,7 @@ Other Style Guides ## jQuery - - [25.1](#25.1) Prefix jQuery object variables with a `$`. jscs: [`requireDollarBeforejQueryAssignment`](http://jscs.info/rule/requireDollarBeforejQueryAssignment) + - [25.1](#25.1) Prefix jQuery object variables with a `$`. ```javascript // bad @@ -2127,9 +1868,6 @@ Other Style Guides // good const $sidebar = $('.sidebar'); - - // good - const $sidebarBtn = $('.sidebar-btn'); ``` - [25.2](#25.2) Cache jQuery lookups. @@ -2184,13 +1922,13 @@ Other Style Guides ## ECMAScript 5 Compatibility - - [26.1](#26.1) Refer to [Kangax](https://twitter.com/kangax/)'s ES5 [compatibility table](http://kangax.github.io/es5-compat-table/). + - [26.1](#26.1) Refer to [Kangax](https://twitter.com/kangax/)'s ES5 [compatibility table](http://kangax.github.com/es5-compat-table/). **[⬆ back to top](#table-of-contents)** ## ECMAScript 6 Styles - - [27.1](#27.1) This is a collection of links to the various ES6 features. + - [27.1](#27.1) This is a collection of links to the various es6 features. 1. [Arrow Functions](#arrow-functions) 1. [Classes](#constructors) @@ -2210,28 +1948,20 @@ Other Style Guides ## Testing - - [28.1](#28.1) **Yup.** + - [28.1](#28.1) **Yup.** ```javascript - function foo() { + function() { return true; } ``` - - [28.2](#28.2) **No, but seriously**: - - Whichever testing framework you use, you should be writing tests! - - Strive to write many small pure functions, and minimize where mutations occur. - - Be cautious about stubs and mocks - they can make your tests more brittle. - - We primarily use [`mocha`](https://www.npmjs.com/package/mocha) 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. - **[⬆ back to top](#table-of-contents)** ## Performance - - [On Layout & Web Performance](http://www.kellegous.com/j/2013/01/26/layout-performance/) + - [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/) - [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2) - [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost) - [Bang Function](http://jsperf.com/bang-function) @@ -2254,24 +1984,24 @@ Other Style Guides **Read This** - - [Standard ECMA-262](http://www.ecma-international.org/ecma-262/6.0/index.html) + - [Annotated ECMAScript 5.1](http://es5.github.com/) **Tools** - Code Style Linters + [ESlint](http://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](http://www.jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/jshintrc) + [JSCS](https://github.com/jscs-dev/node-jscs) - [Airbnb Style Preset](https://github.com/jscs-dev/node-jscs/blob/master/presets/airbnb.json) **Other Style Guides** - [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) - - [jQuery Core Style Guidelines](http://contribute.jquery.org/style-guide/js/) - - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwaldron/idiomatic.js) + - [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines) + - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/) **Other Styles** - - [Naming this in nested functions](https://gist.github.com/cjohansen/4135065) - Christian Johansen + - [Naming this in nested functions](https://gist.github.com/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 @@ -2298,52 +2028,46 @@ Other Style Guides - [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 - - [Third Party JavaScript](https://www.manning.com/books/third-party-javascript) - Ben Vinegar and Anton Kovalyov + - [Third Party JavaScript](http://manning.com/vinegar/) - 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 **Blogs** - [DailyJS](http://dailyjs.com/) - [JavaScript Weekly](http://javascriptweekly.com/) - [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/) - - [Bocoup Weblog](https://bocoup.com/weblog) + - [Bocoup Weblog](http://weblog.bocoup.com/) - [Adequately Good](http://www.adequatelygood.com/) - - [NCZOnline](https://www.nczonline.net/) + - [NCZOnline](http://www.nczonline.net/) - [Perfection Kills](http://perfectionkills.com/) - [Ben Alman](http://benalman.com/) - [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/) - [Dustin Diaz](http://dustindiaz.com/) - - [nettuts](http://code.tutsplus.com/?s=javascript) + - [nettuts](http://net.tutsplus.com/?s=javascript) **Podcasts** - - [JavaScript Jabber](https://devchat.tv/js-jabber/) + - [JavaScript Jabber](http://devchat.tv/js-jabber/) **[⬆ back to top](#table-of-contents)** ## In the Wild - 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. + This is a list of organizations that are using this style guide. Send us a pull request or open an issue and we'll add you to the list. - **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) - **Apartmint**: [apartmint/javascript](https://github.com/apartmint/javascript) - **Avalara**: [avalara/javascript](https://github.com/avalara/javascript) - - **Avant**: [avantcredit/javascript](https://github.com/avantcredit/javascript) - **Billabong**: [billabong/javascript](https://github.com/billabong/javascript) - - **Bisk**: [bisk/javascript](https://github.com/Bisk/javascript/) - **Blendle**: [blendle/javascript](https://github.com/blendle/javascript) - - **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) - **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript) - - **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) - **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) @@ -2351,16 +2075,13 @@ Other Style Guides - **General Electric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript) - **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style) - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript) - - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript-style-guide) + - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript) - **Huballin**: [huballin/javascript](https://github.com/huballin/javascript) - - **HubSpot**: [HubSpot/javascript](https://github.com/HubSpot/javascript) - - **Hyper**: [hyperoslo/javascript-playbook](https://github.com/hyperoslo/javascript-playbook/blob/master/style.md) - **InfoJobs**: [InfoJobs/JavaScript-Style-Guide](https://github.com/InfoJobs/JavaScript-Style-Guide) - **Intent Media**: [intentmedia/javascript](https://github.com/intentmedia/javascript) - **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) - - **Kinetica Solutions**: [kinetica/javascript](https://github.com/kinetica/Javascript-style-guide) + - **Kinetica Solutions**: [kinetica/javascript](https://github.com/kinetica/javascript) - **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) @@ -2371,22 +2092,18 @@ Other Style Guides - **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript) - **Nimbl3**: [nimbl3/javascript](https://github.com/nimbl3/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) - **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/react/blob/master/CONTRIBUTING.md#style-guide](https://github.com/facebook/react/blob/master/CONTRIBUTING.md#style-guide) - **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide) - **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide) - **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide) - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript) - - **Springload**: [springload/javascript](https://github.com/springload/javascript) - - **StudentSphere**: [studentsphere/javascript](https://github.com/studentsphere/guide-javascript) + - **StudentSphere**: [studentsphere/javascript](https://github.com/studentsphere/javascript) - **Target**: [target/javascript](https://github.com/target/javascript) - **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript) - **T4R Technology**: [T4R-Technology/javascript](https://github.com/T4R-Technology/javascript) - **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) - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript) @@ -2400,8 +2117,8 @@ Other Style Guides - ![br](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Brazil.png) **Brazilian Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide) - ![bg](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bulgaria.png) **Bulgarian**: [borislavvv/javascript](https://github.com/borislavvv/javascript) - ![ca](https://raw.githubusercontent.com/fpmweb/javascript-style-guide/master/img/catala.png) **Catalan**: [fpmweb/javascript-style-guide](https://github.com/fpmweb/javascript-style-guide) - - ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Chinese (Simplified)**: [sivan/javascript-style-guide](https://github.com/sivan/javascript-style-guide) - ![tw](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Taiwan.png) **Chinese(Traditional)**: [jigsawye/javascript](https://github.com/jigsawye/javascript) + - ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Chinese(Simplified)**: [sivan/javascript-style-guide](https://github.com/sivan/javascript-style-guide) - ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide) - ![de](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Germany.png) **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide) - ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: [sinkswim/javascript-style-guide](https://github.com/sinkswim/javascript-style-guide) @@ -2429,7 +2146,7 @@ Other Style Guides (The MIT License) -Copyright (c) 2014-2016 Airbnb +Copyright (c) 2014 Airbnb Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -2452,8 +2169,4 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **[⬆ back to top](#table-of-contents)** -## Amendments - -We encourage you to fork this guide and change the rules to fit your team's style guide. Below, you may list some amendments to the style guide. This allows you to periodically update your style guide without having to deal with merge conflicts. - # }; diff --git a/es5/README.md b/es5/README.md index 2d24f1a4a2..fcab603590 100644 --- a/es5/README.md +++ b/es5/README.md @@ -194,7 +194,7 @@ var fullName = 'Bob ' + this.lastName; ``` - - Strings longer than 100 characters should be written across multiple lines using string concatenation. + - Strings longer than 80 characters should be written across multiple lines using string concatenation. - 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). ```javascript @@ -1671,7 +1671,6 @@ - **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide) - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript) - **StudentSphere**: [studentsphere/javascript](https://github.com/studentsphere/javascript) - - **Super**: [SuperJobs/javascript](https://github.com/SuperJobs/javascript) - **Target**: [target/javascript](https://github.com/target/javascript) - **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript) - **T4R Technology**: [T4R-Technology/javascript](https://github.com/T4R-Technology/javascript) diff --git a/linters/.eslintrc b/linters/.eslintrc index 5b840a5f2d..9ded5520e5 100644 --- a/linters/.eslintrc +++ b/linters/.eslintrc @@ -1,6 +1,5 @@ // Use this file as a starting point for your project's .eslintrc. // Copy this file, and add rule overrides as needed. -// See more info at https://github.com/hudl/javascript/tree/master/packages/eslint-config-hudl { "root": true, "extends": "airbnb" diff --git a/linters/README.md b/linters/README.md index 1deac701c7..023aee9791 100644 --- a/linters/README.md +++ b/linters/README.md @@ -1,11 +1,4 @@ ## `.eslintrc` -Our `.eslintrc` requires the following NPM packages: - -``` -npm install --save-dev \ - eslint-config-airbnb \ - eslint \ - babel-eslint \ - eslint-plugin-react -``` +Our `.eslintrc` is dependent on the `eslint-config-hudl` npm package and various peer dependencies. +See [eslint-config-hudl](../packages/eslint-config-hudl) for more installation details. diff --git a/packages/eslint-config-hudl/README.md b/packages/eslint-config-hudl/README.md index 5886d459b5..8644c1a6bd 100644 --- a/packages/eslint-config-hudl/README.md +++ b/packages/eslint-config-hudl/README.md @@ -11,7 +11,7 @@ We export three ESLint configurations for your usage. See [Hudl's Javascript styleguide](https://github.com/hudl/javascript) and the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) -for more information on using config plugins. +for more information on using ESLint config plugins. ### eslint-config-hudl diff --git a/react/README.md b/react/README.md index bf8accc701..5144452fcc 100644 --- a/react/README.md +++ b/react/README.md @@ -5,7 +5,6 @@ ## Table of Contents 1. [Basic Rules](#basic-rules) - 1. [Class vs `React.createClass` vs stateless](#class-vs-reactcreateclass-vs-stateless) 1. [Naming](#naming) 1. [Declaration](#declaration) 1. [Alignment](#alignment) @@ -17,71 +16,44 @@ 1. [Methods](#methods) 1. [Arrow Functions](#arrow-functions) 1. [Ordering](#ordering) - 1. [`isMounted`](#ismounted) ## Basic Rules - Only include one React component per file. - - However, multiple [Stateless, or Pure, Components](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) are allowed per file. eslint: [`react/no-multi-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md#ignorestateless). - Always use JSX syntax. - Do not use `React.createElement` unless you're initializing the app from a file that is not JSX. -## Class vs `React.createClass` vs stateless +## Class vs React.createClass - - If you have internal state and/or refs, prefer `class extends React.Component` over `React.createClass` unless you have a very good reason to use mixins. eslint: [`react/prefer-es6-class`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md) + - Use class extends React.Component unless you have a very good reason to use mixins. ```javascript // bad const Listing = React.createClass({ - // ... render() { - return
{this.state.hello}
; + return
; } }); // good class Listing extends React.Component { - // ... render() { - return
{this.state.hello}
; + return
; } } ``` - And if you don't have state or refs, prefer normal functions (not arrow functions) over classes: - - ```javascript - - // bad - class Listing extends React.Component { - render() { - return
{this.props.hello}
; - } - } - - // bad (since arrow functions do not have a "name" property) - const Listing = ({ hello }) => ( -
{hello}
- ); - - // good - function Listing({ hello }) { - return
{hello}
; - } - ``` - ## Naming - **Extensions**: Use `.jsx` extension for React components. - **Filename**: Use PascalCase for filenames. E.g., `ReservationCard.jsx`. - - **Reference Naming**: Use PascalCase for React components and camelCase for their instances. eslint: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md) - + - **Reference Naming**: Use PascalCase for React components and camelCase for their instances: ```javascript // bad - import reservationCard from './ReservationCard'; + const reservationCard = require('./ReservationCard'); // good - import ReservationCard from './ReservationCard'; + const ReservationCard = require('./ReservationCard'); // bad const ReservationItem = ; @@ -90,22 +62,21 @@ const reservationItem = ; ``` - - **Component Naming**: Use the filename as the component name. For example, `ReservationCard.jsx` should have a reference name of `ReservationCard`. However, for root components of a directory, use `index.jsx` as the filename and use the directory name as the component name: - + **Component Naming**: Use the filename as the component name. For example, `ReservationCard.jsx` should have a reference name of `ReservationCard`. However, for root components of a directory, use `index.jsx` as the filename and use the directory name as the component name: ```javascript // bad - import Footer from './Footer/Footer'; + const Footer = require('./Footer/Footer.jsx') // bad - import Footer from './Footer/index'; + const Footer = require('./Footer/index.jsx') // good - import Footer from './Footer'; + const Footer = require('./Footer') ``` -## Declaration - - Do not use `displayName` for naming components. Instead, name the component by reference. +## Declaration + - Do not use displayName for naming components. Instead, name the component by reference. ```javascript // bad @@ -120,8 +91,7 @@ ``` ## Alignment - - - Follow these alignment styles for JSX syntax. eslint: [`react/jsx-closing-bracket-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md) + - Follow these alignment styles for JS syntax ```javascript // bad @@ -142,17 +112,12 @@ superLongParam="bar" anotherSuperLongParam="baz" > - + ``` ## Quotes - - - Always use double quotes (`"`) for JSX attributes, but single quotes for all other JS. eslint: [`jsx-quotes`](http://eslint.org/docs/rules/jsx-quotes) - - > Why? JSX attributes [can't contain escaped quotes](http://eslint.org/docs/rules/jsx-quotes), so double quotes make conjunctions like `"don't"` easier to type. - > Regular HTML attributes also typically use double quotes instead of single, so JSX attributes mirror this convention. - + - Always use double quotes (`"`) for JSX attributes, but single quotes for all other JS. ```javascript // bad @@ -168,9 +133,7 @@ ``` ## Spacing - - Always include a single space in your self-closing tag. - ```javascript // bad @@ -187,9 +150,7 @@ ``` ## Props - - Always use camelCase for prop names. - ```javascript // bad ``` - - Omit the value of the prop when it is explicitly `true`. eslint: [`react/jsx-boolean-value`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md) - - ```javascript - // bad -