From daea8a638f1f42cd609f1b68b748ad323be31c10 Mon Sep 17 00:00:00 2001 From: Jimmy Jia Date: Fri, 25 Sep 2015 16:15:38 -0400 Subject: [PATCH 1/3] Use rules from eslint-config-defaults --- packages/eslint-config-airbnb/.eslintrc | 5 +- packages/eslint-config-airbnb/base.js | 23 +++ packages/eslint-config-airbnb/base/index.js | 178 ------------------ packages/eslint-config-airbnb/index.js | 20 +- packages/eslint-config-airbnb/package.json | 4 +- packages/eslint-config-airbnb/react.js | 36 ---- .../rules/best-practices.js | 113 +++++++++++ packages/eslint-config-airbnb/rules/errors.js | 60 ++++++ packages/eslint-config-airbnb/rules/es6.js | 51 +++++ packages/eslint-config-airbnb/rules/legacy.js | 16 ++ packages/eslint-config-airbnb/rules/node.js | 23 +++ packages/eslint-config-airbnb/rules/react.js | 78 ++++++++ packages/eslint-config-airbnb/rules/strict.js | 6 + packages/eslint-config-airbnb/rules/style.js | 111 +++++++++++ .../eslint-config-airbnb/rules/variables.js | 26 +++ packages/eslint-config-airbnb/test/.eslintrc | 7 + .../eslint-config-airbnb/test/test-base.js | 33 +++- .../test/test-react-order.js | 9 +- 18 files changed, 556 insertions(+), 243 deletions(-) create mode 100644 packages/eslint-config-airbnb/base.js delete mode 100644 packages/eslint-config-airbnb/base/index.js delete mode 100644 packages/eslint-config-airbnb/react.js create mode 100644 packages/eslint-config-airbnb/rules/best-practices.js create mode 100644 packages/eslint-config-airbnb/rules/errors.js create mode 100644 packages/eslint-config-airbnb/rules/es6.js create mode 100644 packages/eslint-config-airbnb/rules/legacy.js create mode 100644 packages/eslint-config-airbnb/rules/node.js create mode 100644 packages/eslint-config-airbnb/rules/react.js create mode 100644 packages/eslint-config-airbnb/rules/strict.js create mode 100644 packages/eslint-config-airbnb/rules/style.js create mode 100644 packages/eslint-config-airbnb/rules/variables.js create mode 100644 packages/eslint-config-airbnb/test/.eslintrc diff --git a/packages/eslint-config-airbnb/.eslintrc b/packages/eslint-config-airbnb/.eslintrc index cbf450f0..4b3b1fa4 100644 --- a/packages/eslint-config-airbnb/.eslintrc +++ b/packages/eslint-config-airbnb/.eslintrc @@ -3,9 +3,6 @@ "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, - // disabled because I find it tedious to write tests while following this - // rule - "no-shadow": 0 + "comma-dangle": 0 } } diff --git a/packages/eslint-config-airbnb/base.js b/packages/eslint-config-airbnb/base.js new file mode 100644 index 00000000..f3cbf295 --- /dev/null +++ b/packages/eslint-config-airbnb/base.js @@ -0,0 +1,23 @@ +module.exports = { + 'extends': [ + './rules/best-practices.js', + './rules/errors.js', + './rules/es6.js', + './rules/legacy.js', + './rules/node.js', + './rules/strict.js', + './rules/style.js', + './rules/variables.js' + ], + 'parser': 'babel-eslint', + 'env': { + 'browser': true, + 'node': true, + 'amd': false, + 'mocha': false, + 'jasmine': false + }, + 'ecmaFeatures': {}, + 'globals': {}, + 'rules': {} +}; diff --git a/packages/eslint-config-airbnb/base/index.js b/packages/eslint-config-airbnb/base/index.js deleted file mode 100644 index dad7ce9e..00000000 --- a/packages/eslint-config-airbnb/base/index.js +++ /dev/null @@ -1,178 +0,0 @@ -module.exports = { - 'parser': 'babel-eslint', // https://github.com/babel/babel-eslint - '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-undef': 2, // http://eslint.org/docs/rules/no-undef - '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 - 'use-isnan': 2, // http://eslint.org/docs/rules/use-isnan - 'block-scoped-var': 2, // http://eslint.org/docs/rules/block-scoped-var - - /** - * Best practices - */ - '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 - ], - 'id-length': [2, { // http://eslint.org/docs/rules/id-length - 'min': 2, - 'properties': 'never' - }], - '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 - '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 - }], - '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-extra-parens': [2, 'functions'], // http://eslint.org/docs/rules/no-extra-parens - '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, 'always', {// http://eslint.org/docs/rules/spaced-comment - 'exceptions': ['-', '+'], - 'markers': ['=', '!'] // space here to support sprockets directives - }], - } -}; diff --git a/packages/eslint-config-airbnb/index.js b/packages/eslint-config-airbnb/index.js index 3cda9b0f..74d6f345 100644 --- a/packages/eslint-config-airbnb/index.js +++ b/packages/eslint-config-airbnb/index.js @@ -1,13 +1,7 @@ -const reactRules = require('./react'); -const base = require('./base'); - -// clone this so we aren't mutating a module -const eslintrc = JSON.parse(JSON.stringify(base)); - -// manually merge in React rules -eslintrc.plugins = reactRules.plugins; -Object.keys(reactRules.rules).forEach(function assignRule(ruleId) { - eslintrc.rules[ruleId] = reactRules.rules[ruleId]; -}); - -module.exports = eslintrc; +module.exports = { + 'extends': [ + // Need to qualify these here for ESLint to resolve them properly. + 'airbnb/base', + 'airbnb/rules/react.js' + ] +}; diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json index c59c9e4c..87c9da2e 100644 --- a/packages/eslint-config-airbnb/package.json +++ b/packages/eslint-config-airbnb/package.json @@ -4,8 +4,8 @@ "description": "Airbnb's ESLint config, following our styleguide", "main": "index.js", "scripts": { - "lint": "./node_modules/.bin/eslint .", - "test": "./node_modules/.bin/babel-tape-runner ./test/test-*.js" + "lint": "eslint .", + "test": "babel-tape-runner ./test/test-*.js" }, "repository": { "type": "git", diff --git a/packages/eslint-config-airbnb/react.js b/packages/eslint-config-airbnb/react.js deleted file mode 100644 index a0ab17f3..00000000 --- a/packages/eslint-config-airbnb/react.js +++ /dev/null @@ -1,36 +0,0 @@ -module.exports = { - 'plugins': [ - 'react' // https://github.com/yannickcr/eslint-plugin-react - ], - rules: { - /** - * 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-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 - '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 - 'order': [ - 'lifecycle', - '/^on.+$/', - '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', - 'everything-else', - '/^render.+$/', - 'render' - ] - }] - } -}; diff --git a/packages/eslint-config-airbnb/rules/best-practices.js b/packages/eslint-config-airbnb/rules/best-practices.js new file mode 100644 index 00000000..dfb50473 --- /dev/null +++ b/packages/eslint-config-airbnb/rules/best-practices.js @@ -0,0 +1,113 @@ +module.exports = { + 'rules': { + // Enforces getter/setter pairs in objects + 'accessor-pairs': 0, + // treat var statements as if they were block scoped + 'block-scoped-var': 2, + // specify the maximum cyclomatic complexity allowed in a program + 'complexity': [0, 11], + // require return statements to either always or never specify values + 'consistent-return': 2, + // specify curly brace conventions for all control statements + 'curly': [2, 'multi-line'], + // require default case in switch statements + 'default-case': 2, + // encourages use of dot notation whenever possible + 'dot-notation': [2, { 'allowKeywords': true}], + // enforces consistent newlines before or after dots + 'dot-location': 0, + // require the use of === and !== + 'eqeqeq': 2, + // make sure for-in loops have an if statement + 'guard-for-in': 2, + // disallow the use of alert, confirm, and prompt + 'no-alert': 1, + // disallow use of arguments.caller or arguments.callee + 'no-caller': 2, + // disallow division operators explicitly at beginning of regular expression + 'no-div-regex': 0, + // 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, + // disallow comparisons to null without a type-checking operator + 'no-eq-null': 2, + // disallow use of eval() + 'no-eval': 2, + // disallow adding to native types + 'no-extend-native': 2, + // disallow unnecessary function binding + 'no-extra-bind': 2, + // disallow fallthrough of case statements + 'no-fallthrough': 2, + // disallow the use of leading or trailing decimal points in numeric literals + 'no-floating-decimal': 2, + // disallow the type conversions with shorter notations + 'no-implicit-coercion': 0, + // disallow use of eval()-like methods + 'no-implied-eval': 2, + // disallow this keywords outside of classes or class-like objects + 'no-invalid-this': 0, + // disallow usage of __iterator__ property + 'no-iterator': 2, + // disallow use of labeled statements + 'no-labels': 2, + // 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, + // disallow use of multiline strings + 'no-multi-str': 2, + // disallow reassignments of native objects + 'no-native-reassign': 2, + // disallow use of new operator when not part of the assignment or comparison + 'no-new': 2, + // disallow use of new operator for Function object + 'no-new-func': 2, + // disallows creating new instances of String,Number, and Boolean + 'no-new-wrappers': 2, + // disallow use of (old style) octal literals + 'no-octal': 2, + // disallow use of octal escape sequences in string literals, such as + // var foo = 'Copyright \251'; + 'no-octal-escape': 2, + // disallow reassignment of function parameters + 'no-param-reassign': 2, + // disallow use of process.env + 'no-process-env': 0, + // disallow usage of __proto__ property + 'no-proto': 2, + // disallow declaring the same variable more then once + 'no-redeclare': 2, + // disallow use of assignment in return statement + 'no-return-assign': 2, + // disallow use of `javascript:` urls. + 'no-script-url': 2, + // disallow comparisons where both sides are exactly the same + 'no-self-compare': 2, + // disallow use of comma operator + 'no-sequences': 2, + // restrict what can be thrown as an exception + 'no-throw-literal': 2, + // disallow usage of expressions in statement position + 'no-unused-expressions': 2, + // disallow unnecessary .call() and .apply() + 'no-useless-call': 0, + // 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' }], + // disallow use of the with statement + 'no-with': 2, + // require use of the second argument for parseInt() + 'radix': 2, + // requires to declare all vars on top of their containing scope + 'vars-on-top': 2, + // require immediate function invocation to be wrapped in parentheses + 'wrap-iife': [2, 'any'], + // require or disallow Yoda conditions + 'yoda': 2 + } +}; diff --git a/packages/eslint-config-airbnb/rules/errors.js b/packages/eslint-config-airbnb/rules/errors.js new file mode 100644 index 00000000..ec1b1aab --- /dev/null +++ b/packages/eslint-config-airbnb/rules/errors.js @@ -0,0 +1,60 @@ +module.exports = { + 'rules': { + // disallow trailing commas in object literals + 'comma-dangle': [2, 'always-multiline'], + // disallow assignment in conditional expressions + 'no-cond-assign': [2, 'always'], + // disallow use of console + 'no-console': 1, + // disallow use of constant expressions in conditions + 'no-constant-condition': 1, + // disallow control characters in regular expressions + 'no-control-regex': 2, + // disallow use of debugger + 'no-debugger': 1, + // disallow duplicate arguments in functions + 'no-dupe-args': 2, + // 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, + // disallow empty statements + 'no-empty': 2, + // disallow assigning to the exception in a catch block + 'no-ex-assign': 2, + // disallow double-negation boolean casts in a boolean context + 'no-extra-boolean-cast': 0, + // disallow unnecessary parentheses + 'no-extra-parens': [2, 'functions'], + // disallow unnecessary semicolons + 'no-extra-semi': 2, + // disallow overwriting functions written as function declarations + 'no-func-assign': 2, + // disallow function or variable declarations in nested blocks + 'no-inner-declarations': 2, + // disallow invalid regular expression strings in the RegExp constructor + 'no-invalid-regexp': 2, + // 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, + // 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, + // disallow sparse arrays + 'no-sparse-arrays': 2, + // disallow unreachable statements after a return, throw, continue, or break statement + 'no-unreachable': 2, + // disallow comparisons with the value NaN + 'use-isnan': 2, + // ensure JSDoc comments are valid + 'valid-jsdoc': 0, + // 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 + } +}; diff --git a/packages/eslint-config-airbnb/rules/es6.js b/packages/eslint-config-airbnb/rules/es6.js new file mode 100644 index 00000000..b672d4aa --- /dev/null +++ b/packages/eslint-config-airbnb/rules/es6.js @@ -0,0 +1,51 @@ +module.exports = { + 'env': { + 'es6': false + }, + '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': { + // require parens in arrow function arguments + 'arrow-parens': 0, + // require space before/after arrow function's arrow + 'arrow-spacing': 0, + // verify super() callings in constructors + 'constructor-super': 0, + // enforce the spacing around the * in generator functions + 'generator-star-spacing': 0, + // disallow modifying variables of class declarations + 'no-class-assign': 0, + // disallow modifying variables that are declared using const + '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 + 'object-shorthand': 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() + 'prefer-spread': 0, + // suggest using Reflect methods where applicable + 'prefer-reflect': 0, + // disallow generator functions that do not have yield + 'require-yield': 0 + } +}; diff --git a/packages/eslint-config-airbnb/rules/legacy.js b/packages/eslint-config-airbnb/rules/legacy.js new file mode 100644 index 00000000..1d0c5183 --- /dev/null +++ b/packages/eslint-config-airbnb/rules/legacy.js @@ -0,0 +1,16 @@ +module.exports = { + 'rules': { + // specify the maximum depth that blocks can be nested + 'max-depth': [0, 4], + // specify the maximum length of a line in your program + 'max-len': [0, 80, 4], + // limits the number of parameters that can be used in the function declaration. + 'max-params': [0, 3], + // specify the maximum number of statement allowed in a function + 'max-statements': [0, 10], + // disallow use of bitwise operators + 'no-bitwise': 0, + // disallow use of unary operators, ++ and -- + 'no-plusplus': 0 + } +}; diff --git a/packages/eslint-config-airbnb/rules/node.js b/packages/eslint-config-airbnb/rules/node.js new file mode 100644 index 00000000..16b6f20d --- /dev/null +++ b/packages/eslint-config-airbnb/rules/node.js @@ -0,0 +1,23 @@ +module.exports = { + 'env': { + 'node': true + }, + 'rules': { + // enforce return after a callback + 'callback-return': 0, + // enforces error handling in callbacks (node environment) + 'handle-callback-err': 0, + // disallow mixing regular variable and require declarations + 'no-mixed-requires': [0, false], + // disallow use of new operator with the require function + 'no-new-require': 0, + // disallow string concatenation with __dirname and __filename + 'no-path-concat': 0, + // disallow process.exit() + 'no-process-exit': 0, + // restrict usage of specified node modules + 'no-restricted-modules': 0, + // disallow use of synchronous methods (off by default) + 'no-sync': 0 + } +}; diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js new file mode 100644 index 00000000..30783f0e --- /dev/null +++ b/packages/eslint-config-airbnb/rules/react.js @@ -0,0 +1,78 @@ +module.exports = { + 'parser': 'babel-eslint', + 'plugins': [ + 'react' + ], + 'ecmaFeatures': { + 'jsx': false + }, + 'rules': { + // Prevent missing displayName in a React component definition + 'react/display-name': 0, + // Enforce boolean attributes notation in JSX + 'react/jsx-boolean-value': 2, + // Enforce or disallow spaces inside of curly braces in JSX attributes + 'react/jsx-curly-spacing': 0, + // Prevent duplicate props in JSX + 'react/jsx-no-duplicate-props': 0, + // Disallow undeclared variables in JSX + 'react/jsx-no-undef': 2, + // Enforce quote style for JSX attributes + 'react/jsx-quotes': [2, 'double'], + // Enforce propTypes declarations alphabetical sorting + 'react/jsx-sort-prop-types': 0, + // Enforce props alphabetical sorting + 'react/jsx-sort-props': 0, + // Prevent React to be incorrectly marked as unused + 'react/jsx-uses-react': 2, + // Prevent variables used in JSX to be incorrectly marked as unused + 'react/jsx-uses-vars': 2, + // Prevent usage of dangerous JSX properties + 'react/no-danger': 0, + // Prevent usage of setState in componentDidMount + 'react/no-did-mount-set-state': [2, 'allow-in-func'], + // Prevent usage of setState in componentDidUpdate + 'react/no-did-update-set-state': 2, + // Prevent multiple component definition per file + 'react/no-multi-comp': 2, + // Prevent usage of unknown DOM property + 'react/no-unknown-property': 2, + // Prevent missing props validation in a React component definition + 'react/prop-types': 2, + // Prevent missing React when using JSX + 'react/react-in-jsx-scope': 2, + // Restrict file extensions that may be required + 'react/require-extension': 0, + // Prevent extra closing tags for components without children + 'react/self-closing-comp': 2, + // Enforce component methods order + 'react/sort-comp': [2, { + 'order': [ + 'displayName', + 'propTypes', + 'contextTypes', + 'childContextTypes', + 'mixins', + 'statics', + 'defaultProps', + 'constructor', + 'getDefaultProps', + 'getInitialState', + 'getChildContext', + 'componentWillMount', + 'componentDidMount', + 'componentWillReceiveProps', + 'shouldComponentUpdate', + 'componentWillUpdate', + 'componentDidUpdate', + 'componentWillUnmount', + '/^on.+$/', + '/^get.+$/', + '/^render.+$/', + 'render' + ] + }], + // Prevent missing parentheses around multilines JSX + 'react/wrap-multilines': 2 + } +}; diff --git a/packages/eslint-config-airbnb/rules/strict.js b/packages/eslint-config-airbnb/rules/strict.js new file mode 100644 index 00000000..90ac4360 --- /dev/null +++ b/packages/eslint-config-airbnb/rules/strict.js @@ -0,0 +1,6 @@ +module.exports = { + 'rules': { + // require that all functions are run in strict mode + 'strict': [2, 'never'] + } +}; diff --git a/packages/eslint-config-airbnb/rules/style.js b/packages/eslint-config-airbnb/rules/style.js new file mode 100644 index 00000000..107b940b --- /dev/null +++ b/packages/eslint-config-airbnb/rules/style.js @@ -0,0 +1,111 @@ +module.exports = { + 'rules': { + // enforce spacing inside array brackets + 'array-bracket-spacing': 0, + // enforce one true brace style + 'brace-style': [2, '1tbs', {'allowSingleLine': true }], + // require camel case names + 'camelcase': [2, {'properties': 'never'}], + // enforce spacing before and after comma + 'comma-spacing': [2, {'before': false, 'after': true}], + // enforce one true comma style + 'comma-style': [2, 'last'], + // require or disallow padding inside computed properties + '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 + 'eol-last': 2, + // require function expressions to have a name + 'func-names': 1, + // enforces use of function declarations or expressions + 'func-style': 0, + // this option enforces minimum and maximum identifier lengths (variable names, property names etc.) + 'id-length': 0, + // this option sets a specific tab width for your code + 'indent': [2, 2], + // enforces spacing between keys and values in object literal properties + '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 depth callbacks can be nested + 'max-nested-callbacks': 0, + // require a capital letter for constructors + '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 + 'newline-after-var': 0, + // disallow use of the Array constructor + 'no-array-constructor': 0, + // disallow use of the continue statement + 'no-continue': 0, + // disallow comments inline after code + 'no-inline-comments': 0, + // 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': 0, + // disallow multiple empty lines + 'no-multiple-empty-lines': [2, {'max': 2}], + // disallow nested ternary expressions + 'no-nested-ternary': 2, + // disallow use of the Object constructor + 'no-new-object': 2, + // disallow space between function identifier and application + 'no-spaced-func': 2, + // disallow the use of ternary operators + 'no-ternary': 0, + // disallow trailing whitespace at the end of lines + 'no-trailing-spaces': 2, + // disallow dangling underscores in identifiers + 'no-underscore-dangle': 0, + // disallow the use of Boolean literals in conditional expressions + 'no-unneeded-ternary': 0, + // require or disallow padding inside curly braces + 'object-curly-spacing': 0, + // allow just one var statement per function + 'one-var': [2, 'never'], + // require assignment operator shorthand where possible or prohibit it entirely + 'operator-assignment': 0, + // enforce operators to be placed before or after line breaks + 'operator-linebreak': 0, + // enforce padding within blocks + 'padded-blocks': [2, 'never'], + // require quotes around object literal property names + 'quote-props': 0, + // 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}], + // require or disallow use of semicolons instead of ASI + 'semi': [2, 'always'], + // sort variables within the same declaration block + 'sort-vars': 0, + // require a space after certain keywords + 'space-after-keywords': 2, + // require or disallow space before blocks + 'space-before-blocks': 2, + // require or disallow space before function opening parenthesis + 'space-before-function-paren': [2, 'never'], + // require or disallow spaces inside parentheses + 'space-in-parens': 0, + // require spaces around operators + 'space-infix-ops': 2, + // require a space after return, throw, and case + 'space-return-throw-case': 2, + // 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 + }], + // require regex literals to be wrapped in parentheses + 'wrap-regex': 0 + } +}; diff --git a/packages/eslint-config-airbnb/rules/variables.js b/packages/eslint-config-airbnb/rules/variables.js new file mode 100644 index 00000000..3da93fe8 --- /dev/null +++ b/packages/eslint-config-airbnb/rules/variables.js @@ -0,0 +1,26 @@ +module.exports = { + 'rules': { + // enforce or disallow variable initializations at definition + 'init-declarations': 0, + // 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, + // disallow labels that share a name with a variable + 'no-label-var': 0, + // disallow shadowing of names such as arguments + 'no-shadow-restricted-names': 2, + // disallow declaration of variables already declared in the outer scope + 'no-shadow': 2, + // 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, + // 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'}], + // disallow use of variables before they are defined + 'no-use-before-define': 2 + } +}; diff --git a/packages/eslint-config-airbnb/test/.eslintrc b/packages/eslint-config-airbnb/test/.eslintrc new file mode 100644 index 00000000..bb9f4d60 --- /dev/null +++ b/packages/eslint-config-airbnb/test/.eslintrc @@ -0,0 +1,7 @@ +{ + "rules": { + // disabled because I find it tedious to write tests while following this + // rule + "no-shadow": 0 + } +} diff --git a/packages/eslint-config-airbnb/test/test-base.js b/packages/eslint-config-airbnb/test/test-base.js index ecf06cdf..24aa884c 100644 --- a/packages/eslint-config-airbnb/test/test-base.js +++ b/packages/eslint-config-airbnb/test/test-base.js @@ -1,13 +1,30 @@ +import fs from 'fs'; +import path from 'path'; import test from 'tape'; -import base from '../base'; -test('base: does not reference react', t => { - t.plan(2); +const files = { + base: require('../base') +}; - t.notOk(base.plugins, 'plugins is unspecified'); +fs.readdirSync(path.join(__dirname, '../rules')).forEach(name => { + if (name === 'react.js') { + return; + } - // scan rules for react/ and fail if any exist - const reactRuleIds = Object.keys(base.rules) - .filter(ruleId => ruleId.indexOf('react/') === 0); - t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); + files[name] = require(`../rules/${name}`); +}); + +Object.keys(files).forEach(name => { + const config = files[name]; + + test(`${name}: does not reference react`, t => { + t.plan(2); + + t.notOk(config.plugins, 'plugins is unspecified'); + + // scan rules for react/ and fail if any exist + const reactRuleIds = Object.keys(config.rules) + .filter(ruleId => ruleId.indexOf('react/') === 0); + t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); + }); }); diff --git a/packages/eslint-config-airbnb/test/test-react-order.js b/packages/eslint-config-airbnb/test/test-react-order.js index 9ef23f67..2778b2db 100644 --- a/packages/eslint-config-airbnb/test/test-react-order.js +++ b/packages/eslint-config-airbnb/test/test-react-order.js @@ -1,10 +1,15 @@ import test from 'tape'; import { CLIEngine } from 'eslint'; import eslintrc from '../'; +import baseConfig from '../base'; +import reactRules from '../rules/react'; const cli = new CLIEngine({ useEslintrc: false, baseConfig: eslintrc, + + // This rule fails when executing on text. + rules: {indent: 0}, }); function lint(text) { @@ -25,8 +30,8 @@ ${body} test('validate react prop order', t => { t.test('make sure our eslintrc has React linting dependencies', t => { t.plan(2); - t.equal(eslintrc.parser, 'babel-eslint', 'uses babel-eslint'); - t.equal(eslintrc.plugins[0], 'react', 'uses eslint-plugin-react'); + t.equal(baseConfig.parser, 'babel-eslint', 'uses babel-eslint'); + t.equal(reactRules.plugins[0], 'react', 'uses eslint-plugin-react'); }); t.test('passes a good component', t => { From db6c4a8b4e7153f6df84e84eb82204c7e41e0c78 Mon Sep 17 00:00:00 2001 From: Jimmy Jia Date: Fri, 25 Sep 2015 16:22:22 -0400 Subject: [PATCH 2/3] Remove differences from eslint-config-defaults --- packages/eslint-config-airbnb/rules/react.js | 24 ++--------- packages/eslint-config-airbnb/rules/style.js | 2 +- packages/eslint-config-airbnb/test/.eslintrc | 4 +- .../test/test-react-order.js | 42 +++++++++---------- 4 files changed, 29 insertions(+), 43 deletions(-) diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js index 30783f0e..0091c302 100644 --- a/packages/eslint-config-airbnb/rules/react.js +++ b/packages/eslint-config-airbnb/rules/react.js @@ -4,7 +4,7 @@ module.exports = { 'react' ], 'ecmaFeatures': { - 'jsx': false + 'jsx': true }, 'rules': { // Prevent missing displayName in a React component definition @@ -48,26 +48,10 @@ module.exports = { // Enforce component methods order 'react/sort-comp': [2, { 'order': [ - 'displayName', - 'propTypes', - 'contextTypes', - 'childContextTypes', - 'mixins', - 'statics', - 'defaultProps', - 'constructor', - 'getDefaultProps', - 'getInitialState', - 'getChildContext', - 'componentWillMount', - 'componentDidMount', - 'componentWillReceiveProps', - 'shouldComponentUpdate', - 'componentWillUpdate', - 'componentDidUpdate', - 'componentWillUnmount', + 'lifecycle', '/^on.+$/', - '/^get.+$/', + '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', + 'everything-else', '/^render.+$/', 'render' ] diff --git a/packages/eslint-config-airbnb/rules/style.js b/packages/eslint-config-airbnb/rules/style.js index 107b940b..519227ee 100644 --- a/packages/eslint-config-airbnb/rules/style.js +++ b/packages/eslint-config-airbnb/rules/style.js @@ -21,7 +21,7 @@ module.exports = { // enforces use of function declarations or expressions 'func-style': 0, // this option enforces minimum and maximum identifier lengths (variable names, property names etc.) - 'id-length': 0, + 'id-length': [2, {'min': 2, 'properties': 'never'}], // this option sets a specific tab width for your code 'indent': [2, 2], // enforces spacing between keys and values in object literal properties diff --git a/packages/eslint-config-airbnb/test/.eslintrc b/packages/eslint-config-airbnb/test/.eslintrc index bb9f4d60..7f79874e 100644 --- a/packages/eslint-config-airbnb/test/.eslintrc +++ b/packages/eslint-config-airbnb/test/.eslintrc @@ -2,6 +2,8 @@ "rules": { // disabled because I find it tedious to write tests while following this // rule - "no-shadow": 0 + "no-shadow": 0, + // tests uses `t` for tape + "id-length": [2, {"min": 2, "properties": "never", "exceptions": ["t"]}] } } diff --git a/packages/eslint-config-airbnb/test/test-react-order.js b/packages/eslint-config-airbnb/test/test-react-order.js index 2778b2db..606f7236 100644 --- a/packages/eslint-config-airbnb/test/test-react-order.js +++ b/packages/eslint-config-airbnb/test/test-react-order.js @@ -37,13 +37,13 @@ test('validate react prop order', t => { t.test('passes a good component', t => { t.plan(3); const result = lint(wrapComponent(` - componentWillMount() { } - componentDidMount() { } - setFoo() { } - getFoo() { } - setBar() { } - someMethod() { } - renderDogs() { } + componentWillMount() {} + componentDidMount() {} + setFoo() {} + getFoo() {} + setBar() {} + someMethod() {} + renderDogs() {} render() { return
; } `)); @@ -55,13 +55,13 @@ test('validate react prop order', t => { t.test('order: when random method is first', t => { t.plan(2); const result = lint(wrapComponent(` - someMethod() { } - componentWillMount() { } - componentDidMount() { } - setFoo() { } - getFoo() { } - setBar() { } - renderDogs() { } + someMethod() {} + componentWillMount() {} + componentDidMount() {} + setFoo() {} + getFoo() {} + setBar() {} + renderDogs() {} render() { return
; } `)); @@ -72,13 +72,13 @@ test('validate react prop order', t => { t.test('order: when random method after lifecycle methods', t => { t.plan(2); const result = lint(wrapComponent(` - componentWillMount() { } - componentDidMount() { } - someMethod() { } - setFoo() { } - getFoo() { } - setBar() { } - renderDogs() { } + componentWillMount() {} + componentDidMount() {} + someMethod() {} + setFoo() {} + getFoo() {} + setBar() {} + renderDogs() {} render() { return
; } `)); From 9c7674a7b3daad3f26e4a0bb6cf6d8fbec6789be Mon Sep 17 00:00:00 2001 From: Jimmy Jia Date: Fri, 25 Sep 2015 16:27:48 -0400 Subject: [PATCH 3/3] Update for upstream dependencies - react/jsx-quotes has been superseded by jsx-quotes - eqeqeq now covers comparisons to null --- packages/eslint-config-airbnb/package.json | 6 +++--- packages/eslint-config-airbnb/rules/best-practices.js | 2 +- packages/eslint-config-airbnb/rules/react.js | 2 +- packages/eslint-config-airbnb/rules/style.js | 2 ++ 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json index 87c9da2e..39f51262 100644 --- a/packages/eslint-config-airbnb/package.json +++ b/packages/eslint-config-airbnb/package.json @@ -26,10 +26,10 @@ }, "homepage": "https://github.com/airbnb/javascript", "devDependencies": { - "babel-eslint": "4.0.10", + "babel-eslint": "4.1.3", "babel-tape-runner": "1.2.0", - "eslint": "1.3.0", - "eslint-plugin-react": "3.2.3", + "eslint": "1.5.1", + "eslint-plugin-react": "3.4.2", "react": "0.13.3", "tape": "4.2.0" } diff --git a/packages/eslint-config-airbnb/rules/best-practices.js b/packages/eslint-config-airbnb/rules/best-practices.js index dfb50473..9d8199eb 100644 --- a/packages/eslint-config-airbnb/rules/best-practices.js +++ b/packages/eslint-config-airbnb/rules/best-practices.js @@ -31,7 +31,7 @@ module.exports = { // disallow use of labels for anything other then loops and switches 'no-empty-label': 2, // disallow comparisons to null without a type-checking operator - 'no-eq-null': 2, + 'no-eq-null': 0, // disallow use of eval() 'no-eval': 2, // disallow adding to native types diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js index 0091c302..01aa64c3 100644 --- a/packages/eslint-config-airbnb/rules/react.js +++ b/packages/eslint-config-airbnb/rules/react.js @@ -18,7 +18,7 @@ module.exports = { // Disallow undeclared variables in JSX 'react/jsx-no-undef': 2, // Enforce quote style for JSX attributes - 'react/jsx-quotes': [2, 'double'], + 'react/jsx-quotes': 0, // Enforce propTypes declarations alphabetical sorting 'react/jsx-sort-prop-types': 0, // Enforce props alphabetical sorting diff --git a/packages/eslint-config-airbnb/rules/style.js b/packages/eslint-config-airbnb/rules/style.js index 519227ee..fa22403d 100644 --- a/packages/eslint-config-airbnb/rules/style.js +++ b/packages/eslint-config-airbnb/rules/style.js @@ -24,6 +24,8 @@ module.exports = { 'id-length': [2, {'min': 2, 'properties': 'never'}], // this option sets a specific tab width for your code 'indent': [2, 2], + // specify whether double or single quotes should be used in JSX attributes + 'jsx-quotes': 2, // enforces spacing between keys and values in object literal properties 'key-spacing': [2, {'beforeColon': false, 'afterColon': true}], // enforces empty lines around comments