├── .npmrc ├── packages ├── eslint-config-airbnb │ ├── .npmrc │ ├── .editorconfig │ ├── .babelrc │ ├── base.js │ ├── legacy.js │ ├── index.js │ ├── test │ │ ├── .eslintrc │ │ ├── requires.js │ │ ├── test-base.js │ │ └── test-react-order.js │ ├── .eslintrc │ ├── LICENSE.md │ ├── package.json │ ├── whitespace.js │ ├── README.md │ ├── rules │ │ ├── react-a11y.js │ │ └── react.js │ └── CHANGELOG.md ├── eslint-config-airbnb-base │ ├── .npmrc │ ├── .editorconfig │ ├── .babelrc │ ├── rules │ │ ├── strict.js │ │ ├── node.js │ │ ├── variables.js │ │ ├── errors.js │ │ ├── es6.js │ │ ├── imports.js │ │ ├── best-practices.js │ │ └── style.js │ ├── test │ │ ├── .eslintrc │ │ ├── requires.js │ │ └── test-base.js │ ├── .eslintrc │ ├── index.js │ ├── legacy.js │ ├── LICENSE.md │ ├── whitespace.js │ ├── package.json │ ├── README.md │ └── CHANGELOG.md └── eslint-config-haptik │ └── package.json ├── .gitignore ├── linters ├── .eslintrc ├── .jshintrc ├── SublimeLinter │ └── SublimeLinter.sublime-settings └── .markdownlint.json ├── .editorconfig ├── LICENSE.md ├── package.json ├── .travis.yml ├── css-in-javascript └── README.md └── react └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.npmrc: -------------------------------------------------------------------------------- 1 | ../../.npmrc -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.npmrc: -------------------------------------------------------------------------------- 1 | ../../.npmrc -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.editorconfig: -------------------------------------------------------------------------------- 1 | ../../.editorconfig -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.editorconfig: -------------------------------------------------------------------------------- 1 | ../../.editorconfig -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["airbnb"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["airbnb"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | 3 | node_modules 4 | 5 | # Only apps should have lockfiles 6 | yarn.lock 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint-config-airbnb-base'].map(require.resolve), 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/legacy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint-config-airbnb-base/legacy'].map(require.resolve), 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /linters/.eslintrc: -------------------------------------------------------------------------------- 1 | // Use this file as a starting point for your project's .eslintrc. 2 | // Copy this file, and add rule overrides as needed. 3 | { 4 | "extends": "airbnb" 5 | } 6 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/strict.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // babel inserts `'use strict';` for us 4 | strict: ['error', 'never'] 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint-config-airbnb-base', 4 | 'eslint-config-airbnb-base/rules/strict', 5 | './rules/react', 6 | './rules/react-a11y', 7 | ].map(require.resolve), 8 | rules: {} 9 | }; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | # editorconfig-tools is unable to ignore longs strings or urls 11 | max_line_length = null 12 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | // disabled because I find it tedious to write tests while following this rule 4 | "no-shadow": 0, 5 | // tests uses `t` for tape 6 | "id-length": [2, {"min": 2, "properties": "never", "exceptions": ["t"]}], 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | // disabled because I find it tedious to write tests while following this rule 4 | "no-shadow": 0, 5 | 6 | // tests uses `t` for tape 7 | "id-length": [2, {"min": 2, "properties": "never", "exceptions": ["t"]}] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js", 3 | "rules": { 4 | // disable requiring trailing commas because it might be nice to revert to 5 | // being JSON at some point, and I don't want to make big changes now. 6 | "comma-dangle": 0, 7 | // we support node 4 8 | "prefer-destructuring": 0, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js", 3 | "rules": { 4 | // disable requiring trailing commas because it might be nice to revert to 5 | // being JSON at some point, and I don't want to make big changes now. 6 | "comma-dangle": 0, 7 | // we support node 4 8 | "prefer-destructuring": 0, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | './rules/best-practices', 4 | './rules/errors', 5 | './rules/node', 6 | './rules/style', 7 | './rules/variables', 8 | './rules/es6', 9 | './rules/imports', 10 | ].map(require.resolve), 11 | parserOptions: { 12 | ecmaVersion: 2018, 13 | sourceType: 'module', 14 | }, 15 | rules: { 16 | strict: 'error', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | const test = require('tape'); 9 | 10 | test('all entry points parse', (t) => { 11 | t.doesNotThrow(() => require('..'), 'index does not throw'); 12 | t.doesNotThrow(() => require('../legacy'), 'legacy does not throw'); 13 | t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw'); 14 | 15 | t.end(); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | const test = require('tape'); 9 | 10 | test('all entry points parse', (t) => { 11 | t.doesNotThrow(() => require('..'), 'index does not throw'); 12 | t.doesNotThrow(() => require('../base'), 'base does not throw'); 13 | t.doesNotThrow(() => require('../legacy'), 'legacy does not throw'); 14 | t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw'); 15 | 16 | t.end(); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/eslint-config-haptik/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-haptik", 3 | "version": "0.0.1", 4 | "description": "Haptik's ESLint config, based on Airbnb style guide", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm run --silent tests-only" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/hellohaptik/javascript-style-guide.git" 12 | }, 13 | "keywords": [ 14 | "eslint" 15 | ], 16 | "author": "Gopal Ojha", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/hellohaptik/javascript-style-guide/issues" 20 | }, 21 | "homepage": "https://github.com/hellohaptik/javascript-style-guide#readme" 22 | } 23 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/legacy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | './rules/best-practices', 4 | './rules/errors', 5 | './rules/node', 6 | './rules/style', 7 | './rules/variables' 8 | ].map(require.resolve), 9 | env: { 10 | browser: true, 11 | node: true, 12 | amd: false, 13 | mocha: false, 14 | jasmine: false 15 | }, 16 | rules: { 17 | 'comma-dangle': ['error', 'never'], 18 | 'prefer-numeric-literals': 'off', 19 | 'no-restricted-properties': ['error', { 20 | object: 'arguments', 21 | property: 'callee', 22 | message: 'arguments.callee is deprecated', 23 | }, { 24 | property: '__defineGetter__', 25 | message: 'Please use Object.defineProperty instead.', 26 | }, { 27 | property: '__defineSetter__', 28 | message: 'Please use Object.defineProperty instead.', 29 | }], 30 | 'no-var': 'off' 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/test-base.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import test from 'tape'; 4 | 5 | const base = require('../base'); 6 | 7 | const files = { base }; 8 | 9 | fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => { 10 | if (name === 'react.js' || name === 'react-a11y.js') { 11 | return; 12 | } 13 | 14 | // eslint-disable-next-line import/no-dynamic-require 15 | files[name] = require(`../rules/${name}`); // eslint-disable-line global-require 16 | }); 17 | 18 | Object.keys(files).forEach((name) => { 19 | const config = files[name]; 20 | 21 | test(`${name}: does not reference react`, (t) => { 22 | t.plan(2); 23 | 24 | // scan plugins for react and fail if it is found 25 | const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') 26 | && config.plugins.indexOf('react') !== -1; 27 | t.notOk(hasReactPlugin, 'there is no react plugin'); 28 | 29 | // scan rules for react/ and fail if any exist 30 | const reactRuleIds = Object.keys(config.rules) 31 | .filter(ruleId => ruleId.indexOf('react/') === 0); 32 | t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/test-base.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import test from 'tape'; 4 | 5 | import index from '..'; 6 | 7 | const files = { ...{ index } }; // object spread is to test parsing 8 | 9 | fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => { 10 | // eslint-disable-next-line import/no-dynamic-require 11 | files[name] = require(`../rules/${name}`); // eslint-disable-line global-require 12 | }); 13 | 14 | Object.keys(files).forEach(( 15 | name, // trailing function comma is to test parsing 16 | ) => { 17 | const config = files[name]; 18 | 19 | test(`${name}: does not reference react`, (t) => { 20 | t.plan(2); 21 | 22 | // scan plugins for react and fail if it is found 23 | const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') 24 | && config.plugins.indexOf('react') !== -1; 25 | t.notOk(hasReactPlugin, 'there is no react plugin'); 26 | 27 | // scan rules for react/ and fail if any exist 28 | const reactRuleIds = Object.keys(config.rules) 29 | .filter(ruleId => ruleId.indexOf('react/') === 0); 30 | t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/node.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true 4 | }, 5 | 6 | rules: { 7 | // enforce return after a callback 8 | 'callback-return': 'off', 9 | 10 | // require all requires be top-level 11 | // https://eslint.org/docs/rules/global-require 12 | 'global-require': 'error', 13 | 14 | // enforces error handling in callbacks (node environment) 15 | 'handle-callback-err': 'off', 16 | 17 | // disallow use of the Buffer() constructor 18 | // https://eslint.org/docs/rules/no-buffer-constructor 19 | 'no-buffer-constructor': 'error', 20 | 21 | // disallow mixing regular variable and require declarations 22 | 'no-mixed-requires': ['off', false], 23 | 24 | // disallow use of new operator with the require function 25 | 'no-new-require': 'error', 26 | 27 | // disallow string concatenation with __dirname and __filename 28 | // https://eslint.org/docs/rules/no-path-concat 29 | 'no-path-concat': 'error', 30 | 31 | // disallow use of process.env 32 | 'no-process-env': 'off', 33 | 34 | // disallow process.exit() 35 | 'no-process-exit': 'off', 36 | 37 | // restrict usage of specified node modules 38 | 'no-restricted-modules': 'off', 39 | 40 | // disallow use of synchronous methods (off by default) 41 | 'no-sync': 'off', 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /linters/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * ENVIRONMENTS 4 | * ================= 5 | */ 6 | 7 | // Define globals exposed by modern browsers. 8 | "browser": true, 9 | 10 | // Define globals exposed by jQuery. 11 | "jquery": true, 12 | 13 | // Define globals exposed by Node.js. 14 | "node": true, 15 | 16 | // Allow ES6. 17 | "esversion": 6, 18 | 19 | /* 20 | * ENFORCING OPTIONS 21 | * ================= 22 | */ 23 | 24 | // Force all variable names to use either camelCase style or UPPER_CASE 25 | // with underscores. 26 | "camelcase": true, 27 | 28 | // Prohibit use of == and != in favor of === and !==. 29 | "eqeqeq": true, 30 | 31 | // Enforce tab width of 2 spaces. 32 | "indent": 2, 33 | 34 | // Prohibit use of a variable before it is defined. 35 | "latedef": true, 36 | 37 | // Enforce line length to 100 characters 38 | "maxlen": 100, 39 | 40 | // Require capitalized names for constructor functions. 41 | "newcap": true, 42 | 43 | // Enforce use of single quotation marks for strings. 44 | "quotmark": "single", 45 | 46 | // Enforce placing 'use strict' at the top function scope 47 | "strict": true, 48 | 49 | // Prohibit use of explicitly undeclared variables. 50 | "undef": true, 51 | 52 | // Warn when variables are defined but never used. 53 | "unused": true, 54 | 55 | /* 56 | * RELAXING OPTIONS 57 | * ================= 58 | */ 59 | 60 | // Suppress warnings about == null comparisons. 61 | "eqnull": true 62 | } 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "airbnb-style", 3 | "version": "2.0.0", 4 | "description": "A mostly reasonable approach to JavaScript.", 5 | "scripts": { 6 | "preinstall": "npm run install:config && npm run install:config:base", 7 | "install:config": "cd packages/eslint-config-airbnb && npm prune && npm install", 8 | "install:config:base": "cd packages/eslint-config-airbnb-base && npm prune && npm install", 9 | "lint": "markdownlint --config linters/.markdownlint.json README.md */README.md", 10 | "pretest": "npm run --silent lint", 11 | "test": "npm run --silent test:config && npm run --silent test:config:base", 12 | "test:config": "cd packages/eslint-config-airbnb; npm test", 13 | "test:config:base": "cd packages/eslint-config-airbnb-base; npm test", 14 | "pretravis": "npm run --silent lint", 15 | "travis": "npm run --silent travis:config && npm run --silent travis:config:base", 16 | "travis:config": "cd packages/eslint-config-airbnb; npm run travis", 17 | "travis:config:base": "cd packages/eslint-config-airbnb-base; npm run travis" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/airbnb/javascript.git" 22 | }, 23 | "keywords": [ 24 | "style guide", 25 | "lint", 26 | "airbnb", 27 | "es6", 28 | "es2015", 29 | "es2016", 30 | "es2017", 31 | "es2018", 32 | "react", 33 | "jsx" 34 | ], 35 | "author": "Harrison Shoff (https://twitter.com/hshoff)", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/airbnb/javascript/issues" 39 | }, 40 | "homepage": "https://github.com/airbnb/javascript", 41 | "devDependencies": { 42 | "markdownlint-cli": "^0.13.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/variables.js: -------------------------------------------------------------------------------- 1 | const confusingBrowserGlobals = require('confusing-browser-globals'); 2 | 3 | module.exports = { 4 | rules: { 5 | // enforce or disallow variable initializations at definition 6 | 'init-declarations': 'off', 7 | 8 | // disallow the catch clause parameter name being the same as a variable in the outer scope 9 | 'no-catch-shadow': 'off', 10 | 11 | // disallow deletion of variables 12 | 'no-delete-var': 'error', 13 | 14 | // disallow labels that share a name with a variable 15 | // https://eslint.org/docs/rules/no-label-var 16 | 'no-label-var': 'error', 17 | 18 | // disallow specific globals 19 | 'no-restricted-globals': ['error', 'isFinite', 'isNaN'].concat(confusingBrowserGlobals), 20 | 21 | // disallow declaration of variables already declared in the outer scope 22 | 'no-shadow': 'error', 23 | 24 | // disallow shadowing of names such as arguments 25 | 'no-shadow-restricted-names': 'error', 26 | 27 | // disallow use of undeclared variables unless mentioned in a /*global */ block 28 | 'no-undef': 'error', 29 | 30 | // disallow use of undefined when initializing variables 31 | 'no-undef-init': 'error', 32 | 33 | // disallow use of undefined variable 34 | // https://eslint.org/docs/rules/no-undefined 35 | // TODO: enable? 36 | 'no-undefined': 'off', 37 | 38 | // disallow declaration of variables that are not used in the code 39 | 'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }], 40 | 41 | // disallow use of variables before they are defined 42 | 'no-use-before-define': ['error', { functions: true, classes: true, variables: true }], 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "11" 4 | - "10" 5 | - "9" 6 | - "8" 7 | - "7" 8 | - "6" 9 | - "5" 10 | - "4" 11 | before_install: 12 | - 'nvm install-latest-npm' 13 | install: 14 | - 'if [ -n "${PACKAGE-}" ]; then cd "packages/${PACKAGE}"; fi' 15 | - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;' 16 | - 'if [ -n "${ESLINT}" ]; then npm install --no-save "eslint@${ESLINT}"; fi' 17 | script: 18 | - 'if [ -n "${PREPUBLISH-}" ]; then npm run pretravis && npm run prepublish && npm run posttravis; elif [ -n "${LINT-}" ]; then npm run lint; else npm run travis; fi' 19 | sudo: false 20 | env: 21 | matrix: 22 | - 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base' 23 | - 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb' 24 | - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb-base' 25 | - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb' 26 | matrix: 27 | fast_finish: true 28 | include: 29 | - node_js: "lts/*" 30 | env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb-base 31 | - node_js: "lts/*" 32 | env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb 33 | - node_js: "lts/*" 34 | env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base 35 | - node_js: "lts/*" 36 | env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb 37 | - node_js: "lts/*" 38 | env: LINT=true 39 | exclude: 40 | - node_js: "5" 41 | env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base 42 | - node_js: "5" 43 | env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb 44 | - node_js: "4" 45 | env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base 46 | - node_js: "4" 47 | env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb 48 | allow_failures: 49 | - node_js: "9" 50 | - node_js: "7" 51 | - node_js: "5" 52 | - env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb-base 53 | - env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb 54 | - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base 55 | - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb 56 | -------------------------------------------------------------------------------- /linters/SublimeLinter/SublimeLinter.sublime-settings: -------------------------------------------------------------------------------- 1 | /** 2 | * Airbnb JSHint settings for use with SublimeLinter and Sublime Text 2. 3 | * 4 | * 1. Install SublimeLinter at https://github.com/SublimeLinter/SublimeLinter 5 | * 2. Open user preferences for the SublimeLinter package in Sublime Text 2 6 | * * For Mac OS X go to _Sublime Text 2_ > _Preferences_ > _Package Settings_ > _SublimeLinter_ > _Settings - User_ 7 | * 3. Paste the contents of this file into your settings file 8 | * 4. Save the settings file 9 | * 10 | * @version 0.3.0 11 | * @see https://github.com/SublimeLinter/SublimeLinter 12 | * @see http://www.jshint.com/docs/ 13 | */ 14 | { 15 | "jshint_options": 16 | { 17 | /* 18 | * ENVIRONMENTS 19 | * ================= 20 | */ 21 | 22 | // Define globals exposed by modern browsers. 23 | "browser": true, 24 | 25 | // Define globals exposed by jQuery. 26 | "jquery": true, 27 | 28 | // Define globals exposed by Node.js. 29 | "node": true, 30 | 31 | /* 32 | * ENFORCING OPTIONS 33 | * ================= 34 | */ 35 | 36 | // Force all variable names to use either camelCase style or UPPER_CASE 37 | // with underscores. 38 | "camelcase": true, 39 | 40 | // Prohibit use of == and != in favor of === and !==. 41 | "eqeqeq": true, 42 | 43 | // Suppress warnings about == null comparisons. 44 | "eqnull": true, 45 | 46 | // Enforce tab width of 2 spaces. 47 | "indent": 2, 48 | 49 | // Prohibit use of a variable before it is defined. 50 | "latedef": true, 51 | 52 | // Require capitalized names for constructor functions. 53 | "newcap": true, 54 | 55 | // Enforce use of single quotation marks for strings. 56 | "quotmark": "single", 57 | 58 | // Prohibit trailing whitespace. 59 | "trailing": true, 60 | 61 | // Prohibit use of explicitly undeclared variables. 62 | "undef": true, 63 | 64 | // Warn when variables are defined but never used. 65 | "unused": true, 66 | 67 | // Enforce line length to 80 characters 68 | "maxlen": 80, 69 | 70 | // Enforce placing 'use strict' at the top function scope 71 | "strict": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/whitespace.js: -------------------------------------------------------------------------------- 1 | const assign = require('object.assign'); 2 | const entries = require('object.entries'); 3 | const CLIEngine = require('eslint').CLIEngine; 4 | 5 | const baseConfig = require('.'); 6 | 7 | function onlyErrorOnRules(rulesToError, config) { 8 | const errorsOnly = assign({}, config); 9 | const cli = new CLIEngine({ baseConfig: config, useEslintrc: false }); 10 | const baseRules = cli.getConfigForFile('./').rules; 11 | 12 | entries(baseRules).forEach((rule) => { 13 | const ruleName = rule[0]; 14 | const ruleConfig = rule[1]; 15 | 16 | if (rulesToError.indexOf(ruleName) === -1) { 17 | if (Array.isArray(ruleConfig)) { 18 | errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); 19 | } else if (typeof ruleConfig === 'number') { 20 | errorsOnly.rules[ruleName] = 1; 21 | } else { 22 | errorsOnly.rules[ruleName] = 'warn'; 23 | } 24 | } 25 | }); 26 | 27 | return errorsOnly; 28 | } 29 | 30 | module.exports = onlyErrorOnRules([ 31 | 'array-bracket-newline', 32 | 'array-bracket-spacing', 33 | 'array-element-newline', 34 | 'arrow-spacing', 35 | 'block-spacing', 36 | 'comma-spacing', 37 | 'computed-property-spacing', 38 | 'dot-location', 39 | 'eol-last', 40 | 'func-call-spacing', 41 | 'function-paren-newline', 42 | 'generator-star-spacing', 43 | 'implicit-arrow-linebreak', 44 | 'indent', 45 | 'key-spacing', 46 | 'keyword-spacing', 47 | 'line-comment-position', 48 | 'linebreak-style', 49 | 'multiline-ternary', 50 | 'newline-per-chained-call', 51 | 'no-irregular-whitespace', 52 | 'no-mixed-spaces-and-tabs', 53 | 'no-multi-spaces', 54 | 'no-regex-spaces', 55 | 'no-spaced-func', 56 | 'no-trailing-spaces', 57 | 'no-whitespace-before-property', 58 | 'nonblock-statement-body-position', 59 | 'object-curly-newline', 60 | 'object-curly-spacing', 61 | 'object-property-newline', 62 | 'one-var-declaration-per-line', 63 | 'operator-linebreak', 64 | 'padded-blocks', 65 | 'padding-line-between-statements', 66 | 'rest-spread-spacing', 67 | 'semi-spacing', 68 | 'semi-style', 69 | 'space-before-blocks', 70 | 'space-before-function-paren', 71 | 'space-in-parens', 72 | 'space-infix-ops', 73 | 'space-unary-ops', 74 | 'spaced-comment', 75 | 'switch-colon-spacing', 76 | 'template-tag-spacing', 77 | 'import/newline-after-import', 78 | ], baseConfig); 79 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-airbnb-base", 3 | "version": "13.1.0", 4 | "description": "Airbnb's base JS ESLint config, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "prelint": "editorconfig-tools check * rules/* test/*", 8 | "lint": "eslint --report-unused-disable-directives .", 9 | "pretests-only": "node ./test/requires", 10 | "tests-only": "babel-tape-runner ./test/test-*.js", 11 | "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest", 12 | "pretest": "npm run --silent lint", 13 | "test": "npm run --silent tests-only", 14 | "pretravis": ":", 15 | "travis": "npm run --silent test", 16 | "posttravis": ":" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/airbnb/javascript" 21 | }, 22 | "keywords": [ 23 | "eslint", 24 | "eslintconfig", 25 | "config", 26 | "airbnb", 27 | "javascript", 28 | "styleguide", 29 | "es2015", 30 | "es2016", 31 | "es2017", 32 | "es2018" 33 | ], 34 | "author": "Jake Teton-Landis (https://twitter.com/@jitl)", 35 | "contributors": [ 36 | { 37 | "name": "Jake Teton-Landis", 38 | "url": "https://twitter.com/jitl" 39 | }, 40 | { 41 | "name": "Jordan Harband", 42 | "email": "ljharb@gmail.com", 43 | "url": "http://ljharb.codes" 44 | }, 45 | { 46 | "name": "Harrison Shoff", 47 | "url": "https://twitter.com/hshoff" 48 | } 49 | ], 50 | "license": "MIT", 51 | "bugs": { 52 | "url": "https://github.com/airbnb/javascript/issues" 53 | }, 54 | "homepage": "https://github.com/airbnb/javascript", 55 | "devDependencies": { 56 | "babel-preset-airbnb": "^2.5.3", 57 | "babel-tape-runner": "^2.0.1", 58 | "editorconfig-tools": "^0.1.1", 59 | "eslint": "^4.19.1 || ^5.3.0", 60 | "eslint-find-rules": "^3.3.1", 61 | "eslint-plugin-import": "^2.16.0", 62 | "in-publish": "^2.0.0", 63 | "safe-publish-latest": "^1.1.2", 64 | "tape": "^4.10.1" 65 | }, 66 | "peerDependencies": { 67 | "eslint": "^4.19.1 || ^5.3.0", 68 | "eslint-plugin-import": "^2.16.0" 69 | }, 70 | "engines": { 71 | "node": ">= 4" 72 | }, 73 | "dependencies": { 74 | "confusing-browser-globals": "^1.0.5", 75 | "object.assign": "^4.1.0", 76 | "object.entries": "^1.1.0" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-airbnb", 3 | "version": "17.1.0", 4 | "description": "Airbnb's ESLint config, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "prelint": "editorconfig-tools check * rules/* test/*", 8 | "lint": "eslint .", 9 | "pretests-only": "node ./test/requires", 10 | "tests-only": "babel-tape-runner ./test/test-*.js", 11 | "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest", 12 | "pretest": "npm run --silent lint", 13 | "test": "npm run --silent tests-only", 14 | "link:eslint": "cd node_modules/eslint && npm link && cd -", 15 | "pretravis": "npm run link:eslint && cd ../eslint-config-airbnb-base && npm link eslint && npm install && npm link && cd - && npm link --no-save eslint-config-airbnb-base", 16 | "travis": "npm run --silent test", 17 | "posttravis": "npm unlink --no-save eslint-config-airbnb-base eslint >/dev/null &" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/airbnb/javascript" 22 | }, 23 | "keywords": [ 24 | "eslint", 25 | "eslintconfig", 26 | "config", 27 | "airbnb", 28 | "javascript", 29 | "styleguide", 30 | "es2015", 31 | "es2016", 32 | "es2017", 33 | "es2018" 34 | ], 35 | "author": "Jake Teton-Landis (https://twitter.com/@jitl)", 36 | "contributors": [ 37 | { 38 | "name": "Jake Teton-Landis", 39 | "url": "https://twitter.com/jitl" 40 | }, 41 | { 42 | "name": "Jordan Harband", 43 | "email": "ljharb@gmail.com", 44 | "url": "http://ljharb.codes" 45 | }, 46 | { 47 | "name": "Harrison Shoff", 48 | "url": "https://twitter.com/hshoff" 49 | } 50 | ], 51 | "license": "MIT", 52 | "bugs": { 53 | "url": "https://github.com/airbnb/javascript/issues" 54 | }, 55 | "homepage": "https://github.com/airbnb/javascript", 56 | "dependencies": { 57 | "eslint-config-airbnb-base": "^13.1.0", 58 | "object.assign": "^4.1.0", 59 | "object.entries": "^1.1.0" 60 | }, 61 | "devDependencies": { 62 | "babel-preset-airbnb": "^2.5.3", 63 | "babel-tape-runner": "^2.0.1", 64 | "editorconfig-tools": "^0.1.1", 65 | "eslint": "^4.19.1 || ^5.3.0", 66 | "eslint-find-rules": "^3.3.1", 67 | "eslint-plugin-import": "^2.16.0", 68 | "eslint-plugin-jsx-a11y": "^6.2.1", 69 | "eslint-plugin-react": "^7.12.4", 70 | "in-publish": "^2.0.0", 71 | "react": ">= 0.13.0", 72 | "safe-publish-latest": "^1.1.2", 73 | "tape": "^4.10.1" 74 | }, 75 | "peerDependencies": { 76 | "eslint": "^4.19.1 || ^5.3.0", 77 | "eslint-plugin-import": "^2.15.0", 78 | "eslint-plugin-jsx-a11y": "^6.2.0", 79 | "eslint-plugin-react": "^7.12.4" 80 | }, 81 | "engines": { 82 | "node": ">= 4" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/test-react-order.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import { CLIEngine } from 'eslint'; 3 | import eslintrc from '..'; 4 | import reactRules from '../rules/react'; 5 | import reactA11yRules from '../rules/react-a11y'; 6 | 7 | const cli = new CLIEngine({ 8 | useEslintrc: false, 9 | baseConfig: eslintrc, 10 | 11 | rules: { 12 | // It is okay to import devDependencies in tests. 13 | 'import/no-extraneous-dependencies': [2, { devDependencies: true }], 14 | // this doesn't matter for tests 15 | 'lines-between-class-members': 0, 16 | }, 17 | }); 18 | 19 | function lint(text) { 20 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeonfiles 21 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeontext 22 | const linter = cli.executeOnText(text); 23 | return linter.results[0]; 24 | } 25 | 26 | function wrapComponent(body) { 27 | return ` 28 | import React from 'react'; 29 | 30 | export default class MyComponent extends React.Component { 31 | /* eslint no-empty-function: 0, class-methods-use-this: 0 */ 32 | ${body} 33 | } 34 | `; 35 | } 36 | 37 | test('validate react prop order', (t) => { 38 | t.test('make sure our eslintrc has React and JSX linting dependencies', (t) => { 39 | t.plan(2); 40 | t.deepEqual(reactRules.plugins, ['react']); 41 | t.deepEqual(reactA11yRules.plugins, ['jsx-a11y', 'react']); 42 | }); 43 | 44 | t.test('passes a good component', (t) => { 45 | t.plan(3); 46 | const result = lint(wrapComponent(` 47 | componentWillMount() {} 48 | componentDidMount() {} 49 | setFoo() {} 50 | getFoo() {} 51 | setBar() {} 52 | someMethod() {} 53 | renderDogs() {} 54 | render() { return
; }`)); 55 | 56 | t.notOk(result.warningCount, 'no warnings'); 57 | t.notOk(result.errorCount, 'no errors'); 58 | t.deepEquals(result.messages, [], 'no messages in results'); 59 | }); 60 | 61 | t.test('order: when random method is first', (t) => { 62 | t.plan(2); 63 | const result = lint(wrapComponent(` 64 | someMethod() {} 65 | componentWillMount() {} 66 | componentDidMount() {} 67 | setFoo() {} 68 | getFoo() {} 69 | setBar() {} 70 | renderDogs() {} 71 | render() { return
; } 72 | `)); 73 | 74 | t.ok(result.errorCount, 'fails'); 75 | t.equal(result.messages[0].ruleId, 'react/sort-comp', 'fails due to sort'); 76 | }); 77 | 78 | t.test('order: when random method after lifecycle methods', (t) => { 79 | t.plan(2); 80 | const result = lint(wrapComponent(` 81 | componentWillMount() {} 82 | componentDidMount() {} 83 | someMethod() {} 84 | setFoo() {} 85 | getFoo() {} 86 | setBar() {} 87 | renderDogs() {} 88 | render() { return
; } 89 | `)); 90 | 91 | t.ok(result.errorCount, 'fails'); 92 | t.equal(result.messages[0].ruleId, 'react/sort-comp', 'fails due to sort'); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/whitespace.js: -------------------------------------------------------------------------------- 1 | const assign = require('object.assign'); 2 | const entries = require('object.entries'); 3 | const CLIEngine = require('eslint').CLIEngine; 4 | 5 | const baseConfig = require('.'); 6 | 7 | function onlyErrorOnRules(rulesToError, config) { 8 | const errorsOnly = assign({}, config); 9 | const cli = new CLIEngine({ baseConfig: config, useEslintrc: false }); 10 | const baseRules = cli.getConfigForFile('./').rules; 11 | 12 | entries(baseRules).forEach((rule) => { 13 | const ruleName = rule[0]; 14 | const ruleConfig = rule[1]; 15 | 16 | if (rulesToError.indexOf(ruleName) === -1) { 17 | if (Array.isArray(ruleConfig)) { 18 | errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); 19 | } else if (typeof ruleConfig === 'number') { 20 | errorsOnly.rules[ruleName] = 1; 21 | } else { 22 | errorsOnly.rules[ruleName] = 'warn'; 23 | } 24 | } 25 | }); 26 | 27 | return errorsOnly; 28 | } 29 | 30 | module.exports = onlyErrorOnRules([ 31 | 'array-bracket-newline', 32 | 'array-bracket-spacing', 33 | 'array-element-newline', 34 | 'arrow-spacing', 35 | 'block-spacing', 36 | 'comma-spacing', 37 | 'computed-property-spacing', 38 | 'dot-location', 39 | 'eol-last', 40 | 'func-call-spacing', 41 | 'function-paren-newline', 42 | 'generator-star-spacing', 43 | 'implicit-arrow-linebreak', 44 | 'indent', 45 | 'key-spacing', 46 | 'keyword-spacing', 47 | 'line-comment-position', 48 | 'linebreak-style', 49 | 'multiline-ternary', 50 | 'newline-per-chained-call', 51 | 'no-irregular-whitespace', 52 | 'no-mixed-spaces-and-tabs', 53 | 'no-multi-spaces', 54 | 'no-regex-spaces', 55 | 'no-spaced-func', 56 | 'no-trailing-spaces', 57 | 'no-whitespace-before-property', 58 | 'nonblock-statement-body-position', 59 | 'object-curly-newline', 60 | 'object-curly-spacing', 61 | 'object-property-newline', 62 | 'one-var-declaration-per-line', 63 | 'operator-linebreak', 64 | 'padded-blocks', 65 | 'padding-line-between-statements', 66 | 'rest-spread-spacing', 67 | 'semi-spacing', 68 | 'semi-style', 69 | 'space-before-blocks', 70 | 'space-before-function-paren', 71 | 'space-in-parens', 72 | 'space-infix-ops', 73 | 'space-unary-ops', 74 | 'spaced-comment', 75 | 'switch-colon-spacing', 76 | 'template-tag-spacing', 77 | 'import/newline-after-import', 78 | // eslint-plugin-react rules 79 | 'react/jsx-child-element-spacing', 80 | 'react/jsx-closing-bracket-location', 81 | 'react/jsx-closing-tag-location', 82 | 'react/jsx-curly-spacing', 83 | 'react/jsx-equals-spacing', 84 | 'react/jsx-first-prop-newline', 85 | 'react/jsx-indent', 86 | 'react/jsx-indent-props', 87 | 'react/jsx-max-props-per-line', 88 | 'react/jsx-one-expression-per-line', 89 | 'react/jsx-space-before-closing', 90 | 'react/jsx-tag-spacing', 91 | 'react/jsx-wrap-multilines', 92 | ], baseConfig); 93 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-airbnb 2 | 3 | [![npm version](https://badge.fury.io/js/eslint-config-airbnb.svg)](http://badge.fury.io/js/eslint-config-airbnb) 4 | 5 | This package provides Airbnb's .eslintrc as an extensible shared config. 6 | 7 | ## Usage 8 | 9 | We export three ESLint configurations for your usage. 10 | 11 | ### eslint-config-airbnb 12 | 13 | Our default export contains all of our ESLint rules, including ECMAScript 6+ and React. It requires `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, and `eslint-plugin-jsx-a11y`. If you don't need React, see [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 14 | 15 | 1. Install the correct versions of each package, which are listed by the command: 16 | 17 | ```sh 18 | npm info "eslint-config-airbnb@latest" peerDependencies 19 | ``` 20 | 21 | If using **npm 5+**, use this shortcut 22 | 23 | ```sh 24 | npx install-peerdeps --dev eslint-config-airbnb 25 | ``` 26 | 27 | If using **yarn**, you can also use the shortcut described above if you have npm 5+ installed on your machine, as the command will detect that you are using yarn and will act accordingly. 28 | Otherwise, run `npm info "eslint-config-airbnb@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. 29 | 30 | If using **npm < 5**, Linux/OSX users can run 31 | 32 | ```sh 33 | ( 34 | export PKG=eslint-config-airbnb; 35 | npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest" 36 | ) 37 | ``` 38 | 39 | Which produces and runs a command like: 40 | 41 | ```sh 42 | npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# 43 | ``` 44 | 45 | If using **npm < 5**, Windows users can either install all the peer dependencies manually, or use the [install-peerdeps](https://github.com/nathanhleung/install-peerdeps) cli tool. 46 | 47 | ```sh 48 | npm install -g install-peerdeps 49 | install-peerdeps --dev eslint-config-airbnb 50 | ``` 51 | The cli will produce and run a command like: 52 | 53 | ```sh 54 | npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# 55 | ``` 56 | 57 | 2. Add `"extends": "airbnb"` to your .eslintrc 58 | 59 | ### eslint-config-airbnb/whitespace 60 | 61 | This entry point only errors on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb/whitespace.js). 62 | 63 | ### eslint-config-airbnb/base 64 | 65 | This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 66 | 67 | ### eslint-config-airbnb/legacy 68 | 69 | This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 70 | 71 | See [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript) and 72 | the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) 73 | for more information. 74 | 75 | ## Improving this config 76 | 77 | Consider adding test cases if you're making complicated rules changes, like anything involving regexes. Perhaps in a distant future, we could use literate programming to structure our README as test cases for our .eslintrc? 78 | 79 | You can run tests with `npm test`. 80 | 81 | You can make sure this module lints with itself using `npm run lint`. 82 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-airbnb-base 2 | 3 | [![npm version](https://badge.fury.io/js/eslint-config-airbnb-base.svg)](http://badge.fury.io/js/eslint-config-airbnb-base) 4 | 5 | This package provides Airbnb's base JS .eslintrc (without React plugins) as an extensible shared config. 6 | 7 | ## Usage 8 | 9 | We export two ESLint configurations for your usage. 10 | 11 | ### eslint-config-airbnb-base 12 | 13 | Our default export contains all of our ESLint rules, including ECMAScript 6+. It requires `eslint` and `eslint-plugin-import`. 14 | 15 | 1. Install the correct versions of each package, which are listed by the command: 16 | 17 | ```sh 18 | npm info "eslint-config-airbnb-base@latest" peerDependencies 19 | ``` 20 | 21 | If using **npm 5+**, use this shortcut 22 | 23 | ```sh 24 | npx install-peerdeps --dev eslint-config-airbnb-base 25 | ``` 26 | 27 | If using **yarn**, you can also use the shortcut described above if you have npm 5+ installed on your machine, as the command will detect that you are using yarn and will act accordingly. 28 | Otherwise, run `npm info "eslint-config-airbnb-base@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. 29 | 30 | 31 | If using **npm < 5**, Linux/OSX users can run 32 | 33 | ```sh 34 | ( 35 | export PKG=eslint-config-airbnb-base; 36 | npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest" 37 | ) 38 | ``` 39 | 40 | Which produces and runs a command like: 41 | 42 | ```sh 43 | npm install --save-dev eslint-config-airbnb-base eslint@^#.#.# eslint-plugin-import@^#.#.# 44 | ``` 45 | 46 | If using **npm < 5**, Windows users can either install all the peer dependencies manually, or use the [install-peerdeps](https://github.com/nathanhleung/install-peerdeps) cli tool. 47 | 48 | ```sh 49 | npm install -g install-peerdeps 50 | install-peerdeps --dev eslint-config-airbnb-base 51 | ``` 52 | 53 | The cli will produce and run a command like: 54 | 55 | ```sh 56 | npm install --save-dev eslint-config-airbnb-base eslint@^#.#.# eslint-plugin-import@^#.#.# 57 | ``` 58 | 59 | 2. Add `"extends": "airbnb-base"` to your .eslintrc. 60 | 61 | ### eslint-config-airbnb-base/legacy 62 | 63 | Lints ES5 and below. Requires `eslint` and `eslint-plugin-import`. 64 | 65 | 1. Install the correct versions of each package, which are listed by the command: 66 | 67 | ```sh 68 | npm info "eslint-config-airbnb-base@latest" peerDependencies 69 | ``` 70 | 71 | Linux/OSX users can run 72 | ```sh 73 | ( 74 | export PKG=eslint-config-airbnb-base; 75 | npm info "$PKG" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG" 76 | ) 77 | ``` 78 | 79 | Which produces and runs a command like: 80 | 81 | ```sh 82 | npm install --save-dev eslint-config-airbnb-base eslint@^3.0.1 eslint-plugin-import@^1.10.3 83 | ``` 84 | 85 | 2. Add `"extends": "airbnb-base/legacy"` to your .eslintrc 86 | 87 | See [Airbnb's overarching ESLint config](https://npmjs.com/eslint-config-airbnb), [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript), and the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information. 88 | 89 | ### eslint-config-airbnb-base/whitespace 90 | 91 | This entry point only errors on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/whitespace.js). 92 | 93 | ## Improving this config 94 | 95 | Consider adding test cases if you're making complicated rules changes, like anything involving regexes. Perhaps in a distant future, we could use literate programming to structure our README as test cases for our .eslintrc? 96 | 97 | You can run tests with `npm test`. 98 | 99 | You can make sure this module lints with itself using `npm run lint`. 100 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/errors.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // Enforce “for” loop update clause moving the counter in the right direction 4 | // https://eslint.org/docs/rules/for-direction 5 | 'for-direction': 'error', 6 | 7 | // Enforces that a return statement is present in property getters 8 | // https://eslint.org/docs/rules/getter-return 9 | 'getter-return': ['error', { allowImplicit: true }], 10 | 11 | // disallow using an async function as a Promise executor 12 | // https://eslint.org/docs/rules/no-async-promise-executor 13 | // TODO: enable, semver-major 14 | 'no-async-promise-executor': 'off', 15 | 16 | // Disallow await inside of loops 17 | // https://eslint.org/docs/rules/no-await-in-loop 18 | 'no-await-in-loop': 'error', 19 | 20 | // Disallow comparisons to negative zero 21 | // https://eslint.org/docs/rules/no-compare-neg-zero 22 | 'no-compare-neg-zero': 'error', 23 | 24 | // disallow assignment in conditional expressions 25 | 'no-cond-assign': ['error', 'always'], 26 | 27 | // disallow use of console 28 | 'no-console': 'warn', 29 | 30 | // disallow use of constant expressions in conditions 31 | 'no-constant-condition': 'warn', 32 | 33 | // disallow control characters in regular expressions 34 | 'no-control-regex': 'error', 35 | 36 | // disallow use of debugger 37 | 'no-debugger': 'error', 38 | 39 | // disallow duplicate arguments in functions 40 | 'no-dupe-args': 'error', 41 | 42 | // disallow duplicate keys when creating object literals 43 | 'no-dupe-keys': 'error', 44 | 45 | // disallow a duplicate case label. 46 | 'no-duplicate-case': 'error', 47 | 48 | // disallow empty statements 49 | 'no-empty': 'error', 50 | 51 | // disallow the use of empty character classes in regular expressions 52 | 'no-empty-character-class': 'error', 53 | 54 | // disallow assigning to the exception in a catch block 55 | 'no-ex-assign': 'error', 56 | 57 | // disallow double-negation boolean casts in a boolean context 58 | // https://eslint.org/docs/rules/no-extra-boolean-cast 59 | 'no-extra-boolean-cast': 'error', 60 | 61 | // disallow unnecessary parentheses 62 | // https://eslint.org/docs/rules/no-extra-parens 63 | 'no-extra-parens': ['off', 'all', { 64 | conditionalAssign: true, 65 | nestedBinaryExpressions: false, 66 | returnAssign: false, 67 | ignoreJSX: 'all', // delegate to eslint-plugin-react 68 | enforceForArrowConditionals: false, 69 | }], 70 | 71 | // disallow unnecessary semicolons 72 | 'no-extra-semi': 'error', 73 | 74 | // disallow overwriting functions written as function declarations 75 | 'no-func-assign': 'error', 76 | 77 | // disallow function or variable declarations in nested blocks 78 | 'no-inner-declarations': 'error', 79 | 80 | // disallow invalid regular expression strings in the RegExp constructor 81 | 'no-invalid-regexp': 'error', 82 | 83 | // disallow irregular whitespace outside of strings and comments 84 | 'no-irregular-whitespace': 'error', 85 | 86 | // Disallow characters which are made with multiple code points in character class syntax 87 | // https://eslint.org/docs/rules/no-misleading-character-class 88 | // TODO: enable, semver-major 89 | 'no-misleading-character-class': 'off', 90 | 91 | // disallow the use of object properties of the global object (Math and JSON) as functions 92 | 'no-obj-calls': 'error', 93 | 94 | // disallow use of Object.prototypes builtins directly 95 | // https://eslint.org/docs/rules/no-prototype-builtins 96 | 'no-prototype-builtins': 'error', 97 | 98 | // disallow multiple spaces in a regular expression literal 99 | 'no-regex-spaces': 'error', 100 | 101 | // disallow sparse arrays 102 | 'no-sparse-arrays': 'error', 103 | 104 | // Disallow template literal placeholder syntax in regular strings 105 | // https://eslint.org/docs/rules/no-template-curly-in-string 106 | 'no-template-curly-in-string': 'error', 107 | 108 | // Avoid code that looks like two expressions but is actually one 109 | // https://eslint.org/docs/rules/no-unexpected-multiline 110 | 'no-unexpected-multiline': 'error', 111 | 112 | // disallow unreachable statements after a return, throw, continue, or break statement 113 | 'no-unreachable': 'error', 114 | 115 | // disallow return/throw/break/continue inside finally blocks 116 | // https://eslint.org/docs/rules/no-unsafe-finally 117 | 'no-unsafe-finally': 'error', 118 | 119 | // disallow negating the left operand of relational operators 120 | // https://eslint.org/docs/rules/no-unsafe-negation 121 | 'no-unsafe-negation': 'error', 122 | // disallow negation of the left operand of an in expression 123 | // deprecated in favor of no-unsafe-negation 124 | 'no-negated-in-lhs': 'off', 125 | 126 | // Disallow assignments that can lead to race conditions due to usage of await or yield 127 | // https://eslint.org/docs/rules/require-atomic-updates 128 | // TODO: enable, semver-major 129 | 'require-atomic-updates': 'off', 130 | 131 | // disallow comparisons with the value NaN 132 | 'use-isnan': 'error', 133 | 134 | // ensure JSDoc comments are valid 135 | // https://eslint.org/docs/rules/valid-jsdoc 136 | 'valid-jsdoc': 'off', 137 | 138 | // ensure that the results of typeof are compared against a valid string 139 | // https://eslint.org/docs/rules/valid-typeof 140 | 'valid-typeof': ['error', { requireStringLiterals: true }], 141 | } 142 | }; 143 | -------------------------------------------------------------------------------- /linters/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "Be explicit by listing every available rule. https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md", 3 | "comment": "Note that there will be numeric gaps, not every MD number is implemented in markdownlint.", 4 | 5 | "comment": "MD001: Header levels should only increment by one level at a time.", 6 | "header-increment": true, 7 | 8 | "comment": "MD002: First header should be a top level header.", 9 | "first-header-h1": true, 10 | 11 | "comment": "MD003: Header style: start with hashes.", 12 | "header-style": { 13 | "style": "atx" 14 | }, 15 | 16 | "comment": "MD004: Unordered list style", 17 | "ul-style": { 18 | "style": "dash" 19 | }, 20 | 21 | "comment": "MD005: Consistent indentation for list items at the same level.", 22 | "list-indent": true, 23 | 24 | "comment": "MD006: Consider starting bulleted lists at the beginning of the line.", 25 | "ul-start-left": false, 26 | 27 | "comment": "MD007: Unordered list indentation: 2 spaces.", 28 | "ul-indent": { 29 | "indent": 2 30 | }, 31 | 32 | "comment": "MD009: Disallow trailing spaces!", 33 | "no-trailing-spaces": { 34 | "br_spaces": 0, 35 | "comment": "Empty lines inside list items should not be indented.", 36 | "list_item_empty_lines": false 37 | }, 38 | 39 | "comment": "MD010: No hard tabs, not even in code blocks.", 40 | "no-hard-tabs": { 41 | "code_blocks": true 42 | }, 43 | 44 | "comment": "MD011: Prevent reversed link syntax", 45 | "no-reversed-links": true, 46 | 47 | "comment": "MD012: Disallow multiple consecutive blank lines.", 48 | "no-multiple-blanks": { 49 | "maximum": 1 50 | }, 51 | 52 | "comment": "MD013: Line length", 53 | "line-length": false, 54 | 55 | "comment": "MD014: Disallow use of dollar signs($) before commands without showing output.", 56 | "commands-show-output": true, 57 | 58 | "comment": "MD018: Disallow space after hash on atx style header.", 59 | "no-missing-space-atx": true, 60 | 61 | "comment": "MD019: Disallow multiple spaces after hash on atx style header.", 62 | "no-multiple-space-atx": true, 63 | 64 | "comment": "MD020: No space should be inside hashes on closed atx style header.", 65 | "no-missing-space-closed-atx": true, 66 | 67 | "comment": "MD021: Disallow multiple spaces inside hashes on closed atx style header.", 68 | "no-multiple-space-closed-atx": true, 69 | 70 | "comment": "MD022: Headers should be surrounded by blank lines.", 71 | "comment": "Some headers have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers", 72 | "blanks-around-headers": false, 73 | 74 | "comment": "MD023: Headers must start at the beginning of the line.", 75 | "header-start-left": true, 76 | 77 | "comment": "MD024: Disallow multiple headers with the same content.", 78 | "no-duplicate-header": true, 79 | 80 | "comment": "MD025: Disallow multiple top level headers in the same document.", 81 | "comment": "Gotta have a matching closing brace at the end.", 82 | "single-h1": false, 83 | 84 | "comment": "MD026: Disallow trailing punctuation in header.", 85 | "comment": "You must have a semicolon after the ending closing brace.", 86 | "no-trailing-punctuation": { 87 | "punctuation" : ".,:!?" 88 | }, 89 | "comment": "MD027: Dissalow multiple spaces after blockquote symbol", 90 | "no-multiple-space-blockquote": true, 91 | 92 | "comment": "MD028: Blank line inside blockquote", 93 | "comment": "Some 'Why?' and 'Why not?' blocks are separated by a blank line", 94 | "no-blanks-blockquote": false, 95 | 96 | "comment": "MD029: Ordered list item prefix", 97 | "ol-prefix": { 98 | "style": "one" 99 | }, 100 | 101 | "comment": "MD030: Spaces after list markers", 102 | "list-marker-space": { 103 | "ul_single": 1, 104 | "ol_single": 1, 105 | "ul_multi": 1, 106 | "ol_multi": 1 107 | }, 108 | 109 | "comment": "MD031: Fenced code blocks should be surrounded by blank lines", 110 | "blanks-around-fences": true, 111 | 112 | "comment": "MD032: Lists should be surrounded by blank lines", 113 | "comment": "Some lists have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers", 114 | "blanks-around-lists": false, 115 | 116 | "comment": "MD033: Disallow inline HTML", 117 | "comment": "HTML is needed for explicit anchors", 118 | "no-inline-html": false, 119 | 120 | "comment": "MD034: No bare URLs should be used", 121 | "no-bare-urls": true, 122 | 123 | "comment": "MD035: Horizontal rule style", 124 | "hr-style": { 125 | "style": "consistent" 126 | }, 127 | 128 | "comment": "MD036: Do not use emphasis instead of a header.", 129 | "no-emphasis-as-header": false, 130 | 131 | "comment": "MD037: Disallow spaces inside emphasis markers.", 132 | "no-space-in-emphasis": true, 133 | 134 | "comment": "MD038: Disallow spaces inside code span elements.", 135 | "no-space-in-code": true, 136 | 137 | "comment": "MD039: Disallow spaces inside link text.", 138 | "no-space-in-links": true, 139 | 140 | "comment": "MD040: Fenced code blocks should have a language specified.", 141 | "fenced-code-language": true, 142 | 143 | "comment": "MD041: First line in file should be a top level header.", 144 | "first-line-h1": true, 145 | 146 | "comment": "MD042: No empty links", 147 | "no-empty-links": true, 148 | 149 | "comment": "MD043: Required header structure.", 150 | "required-headers": false, 151 | 152 | "comment": "MD044: Proper names should have the correct capitalization.", 153 | "proper-names": false 154 | } 155 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/es6.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true 4 | }, 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | sourceType: 'module', 8 | ecmaFeatures: { 9 | generators: false, 10 | objectLiteralDuplicateProperties: false 11 | } 12 | }, 13 | 14 | rules: { 15 | // enforces no braces where they can be omitted 16 | // https://eslint.org/docs/rules/arrow-body-style 17 | // TODO: enable requireReturnForObjectLiteral? 18 | 'arrow-body-style': ['error', 'as-needed', { 19 | requireReturnForObjectLiteral: false, 20 | }], 21 | 22 | // require parens in arrow function arguments 23 | // https://eslint.org/docs/rules/arrow-parens 24 | 'arrow-parens': ['error', 'as-needed', { 25 | requireForBlockBody: true, 26 | }], 27 | 28 | // require space before/after arrow function's arrow 29 | // https://eslint.org/docs/rules/arrow-spacing 30 | 'arrow-spacing': ['error', { before: true, after: true }], 31 | 32 | // verify super() callings in constructors 33 | 'constructor-super': 'error', 34 | 35 | // enforce the spacing around the * in generator functions 36 | // https://eslint.org/docs/rules/generator-star-spacing 37 | 'generator-star-spacing': ['error', { before: false, after: true }], 38 | 39 | // disallow modifying variables of class declarations 40 | // https://eslint.org/docs/rules/no-class-assign 41 | 'no-class-assign': 'error', 42 | 43 | // disallow arrow functions where they could be confused with comparisons 44 | // https://eslint.org/docs/rules/no-confusing-arrow 45 | 'no-confusing-arrow': ['error', { 46 | allowParens: true, 47 | }], 48 | 49 | // disallow modifying variables that are declared using const 50 | 'no-const-assign': 'error', 51 | 52 | // disallow duplicate class members 53 | // https://eslint.org/docs/rules/no-dupe-class-members 54 | 'no-dupe-class-members': 'error', 55 | 56 | // disallow importing from the same path more than once 57 | // https://eslint.org/docs/rules/no-duplicate-imports 58 | // replaced by https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 59 | 'no-duplicate-imports': 'off', 60 | 61 | // disallow symbol constructor 62 | // https://eslint.org/docs/rules/no-new-symbol 63 | 'no-new-symbol': 'error', 64 | 65 | // disallow specific imports 66 | // https://eslint.org/docs/rules/no-restricted-imports 67 | 'no-restricted-imports': ['off', { 68 | paths: [], 69 | patterns: [] 70 | }], 71 | 72 | // disallow to use this/super before super() calling in constructors. 73 | // https://eslint.org/docs/rules/no-this-before-super 74 | 'no-this-before-super': 'error', 75 | 76 | // disallow useless computed property keys 77 | // https://eslint.org/docs/rules/no-useless-computed-key 78 | 'no-useless-computed-key': 'error', 79 | 80 | // disallow unnecessary constructor 81 | // https://eslint.org/docs/rules/no-useless-constructor 82 | 'no-useless-constructor': 'error', 83 | 84 | // disallow renaming import, export, and destructured assignments to the same name 85 | // https://eslint.org/docs/rules/no-useless-rename 86 | 'no-useless-rename': ['error', { 87 | ignoreDestructuring: false, 88 | ignoreImport: false, 89 | ignoreExport: false, 90 | }], 91 | 92 | // require let or const instead of var 93 | 'no-var': 'error', 94 | 95 | // require method and property shorthand syntax for object literals 96 | // https://eslint.org/docs/rules/object-shorthand 97 | 'object-shorthand': ['error', 'always', { 98 | ignoreConstructors: false, 99 | avoidQuotes: true, 100 | }], 101 | 102 | // suggest using arrow functions as callbacks 103 | 'prefer-arrow-callback': ['error', { 104 | allowNamedFunctions: false, 105 | allowUnboundThis: true, 106 | }], 107 | 108 | // suggest using of const declaration for variables that are never modified after declared 109 | 'prefer-const': ['error', { 110 | destructuring: 'any', 111 | ignoreReadBeforeAssign: true, 112 | }], 113 | 114 | // Prefer destructuring from arrays and objects 115 | // https://eslint.org/docs/rules/prefer-destructuring 116 | 'prefer-destructuring': ['error', { 117 | VariableDeclarator: { 118 | array: false, 119 | object: true, 120 | }, 121 | AssignmentExpression: { 122 | array: true, 123 | object: true, 124 | }, 125 | }, { 126 | enforceForRenamedProperties: false, 127 | }], 128 | 129 | // disallow parseInt() in favor of binary, octal, and hexadecimal literals 130 | // https://eslint.org/docs/rules/prefer-numeric-literals 131 | 'prefer-numeric-literals': 'error', 132 | 133 | // suggest using Reflect methods where applicable 134 | // https://eslint.org/docs/rules/prefer-reflect 135 | 'prefer-reflect': 'off', 136 | 137 | // use rest parameters instead of arguments 138 | // https://eslint.org/docs/rules/prefer-rest-params 139 | 'prefer-rest-params': 'error', 140 | 141 | // suggest using the spread operator instead of .apply() 142 | // https://eslint.org/docs/rules/prefer-spread 143 | 'prefer-spread': 'error', 144 | 145 | // suggest using template literals instead of string concatenation 146 | // https://eslint.org/docs/rules/prefer-template 147 | 'prefer-template': 'error', 148 | 149 | // disallow generator functions that do not have yield 150 | // https://eslint.org/docs/rules/require-yield 151 | 'require-yield': 'error', 152 | 153 | // enforce spacing between object rest-spread 154 | // https://eslint.org/docs/rules/rest-spread-spacing 155 | 'rest-spread-spacing': ['error', 'never'], 156 | 157 | // import sorting 158 | // https://eslint.org/docs/rules/sort-imports 159 | 'sort-imports': ['off', { 160 | ignoreCase: false, 161 | ignoreMemberSort: false, 162 | memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], 163 | }], 164 | 165 | // require a Symbol description 166 | // https://eslint.org/docs/rules/symbol-description 167 | 'symbol-description': 'error', 168 | 169 | // enforce usage of spacing in template strings 170 | // https://eslint.org/docs/rules/template-curly-spacing 171 | 'template-curly-spacing': 'error', 172 | 173 | // enforce spacing around the * in yield* expressions 174 | // https://eslint.org/docs/rules/yield-star-spacing 175 | 'yield-star-spacing': ['error', 'after'] 176 | } 177 | }; 178 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/rules/react-a11y.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'jsx-a11y', 4 | 'react' 5 | ], 6 | 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | }, 12 | 13 | rules: { 14 | // Enforce that anchors have content 15 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md 16 | 'jsx-a11y/anchor-has-content': ['error', { components: [] }], 17 | 18 | // Require ARIA roles to be valid and non-abstract 19 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md 20 | 'jsx-a11y/aria-role': ['error', { ignoreNonDom: false }], 21 | 22 | // Enforce all aria-* props are valid. 23 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md 24 | 'jsx-a11y/aria-props': 'error', 25 | 26 | // Enforce ARIA state and property values are valid. 27 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md 28 | 'jsx-a11y/aria-proptypes': 'error', 29 | 30 | // Enforce that elements that do not support ARIA roles, states, and 31 | // properties do not have those attributes. 32 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md 33 | 'jsx-a11y/aria-unsupported-elements': 'error', 34 | 35 | // Enforce that all elements that require alternative text have meaningful information 36 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md 37 | 'jsx-a11y/alt-text': ['error', { 38 | elements: ['img', 'object', 'area', 'input[type="image"]'], 39 | img: [], 40 | object: [], 41 | area: [], 42 | 'input[type="image"]': [], 43 | }], 44 | 45 | // Prevent img alt text from containing redundant words like "image", "picture", or "photo" 46 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md 47 | 'jsx-a11y/img-redundant-alt': 'error', 48 | 49 | // require that JSX labels use "htmlFor" 50 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md 51 | 'jsx-a11y/label-has-for': ['error', { 52 | components: [], 53 | required: { 54 | every: ['nesting', 'id'], 55 | }, 56 | allowChildren: false, 57 | }], 58 | 59 | // Enforce that a label tag has a text label and an associated control. 60 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md 61 | 'jsx-a11y/label-has-associated-control': ['error', { 62 | labelComponents: [], 63 | labelAttributes: [], 64 | controlComponents: [], 65 | assert: 'both', 66 | depth: 25 67 | }], 68 | 69 | // require that mouseover/out come with focus/blur, for keyboard-only users 70 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md 71 | 'jsx-a11y/mouse-events-have-key-events': 'error', 72 | 73 | // Prevent use of `accessKey` 74 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md 75 | 'jsx-a11y/no-access-key': 'error', 76 | 77 | // require onBlur instead of onChange 78 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md 79 | 'jsx-a11y/no-onchange': 'off', 80 | 81 | // Elements with an interactive role and interaction handlers must be focusable 82 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md 83 | 'jsx-a11y/interactive-supports-focus': 'error', 84 | 85 | // Enforce that elements with ARIA roles must have all required attributes 86 | // for that role. 87 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md 88 | 'jsx-a11y/role-has-required-aria-props': 'error', 89 | 90 | // Enforce that elements with explicit or implicit roles defined contain 91 | // only aria-* properties supported by that role. 92 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md 93 | 'jsx-a11y/role-supports-aria-props': 'error', 94 | 95 | // Enforce tabIndex value is not greater than zero. 96 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md 97 | 'jsx-a11y/tabindex-no-positive': 'error', 98 | 99 | // ensure tags have content and are not aria-hidden 100 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md 101 | 'jsx-a11y/heading-has-content': ['error', { components: [''] }], 102 | 103 | // require HTML elements to have a "lang" prop 104 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md 105 | 'jsx-a11y/html-has-lang': 'error', 106 | 107 | // require HTML element's lang prop to be valid 108 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md 109 | 'jsx-a11y/lang': 'error', 110 | 111 | // prevent distracting elements, like and 112 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md 113 | 'jsx-a11y/no-distracting-elements': ['error', { 114 | elements: ['marquee', 'blink'], 115 | }], 116 | 117 | // only allow to have the "scope" attr 118 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md 119 | 'jsx-a11y/scope': 'error', 120 | 121 | // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress 122 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md 123 | 'jsx-a11y/click-events-have-key-events': 'error', 124 | 125 | // Enforce that DOM elements without semantic behavior not have interaction handlers 126 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md 127 | 'jsx-a11y/no-static-element-interactions': ['error', { 128 | handlers: [ 129 | 'onClick', 130 | 'onMouseDown', 131 | 'onMouseUp', 132 | 'onKeyPress', 133 | 'onKeyDown', 134 | 'onKeyUp', 135 | ] 136 | }], 137 | 138 | // A non-interactive element does not support event handlers (mouse and key handlers) 139 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md 140 | 'jsx-a11y/no-noninteractive-element-interactions': ['error', { 141 | handlers: [ 142 | 'onClick', 143 | 'onMouseDown', 144 | 'onMouseUp', 145 | 'onKeyPress', 146 | 'onKeyDown', 147 | 'onKeyUp', 148 | ] 149 | }], 150 | 151 | // ensure emoji are accessible 152 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md 153 | 'jsx-a11y/accessible-emoji': 'error', 154 | 155 | // elements with aria-activedescendant must be tabbable 156 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md 157 | 'jsx-a11y/aria-activedescendant-has-tabindex': 'error', 158 | 159 | // ensure iframe elements have a unique title 160 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md 161 | 'jsx-a11y/iframe-has-title': 'error', 162 | 163 | // prohibit autoFocus prop 164 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md 165 | 'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }], 166 | 167 | // ensure HTML elements do not specify redundant ARIA roles 168 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md 169 | 'jsx-a11y/no-redundant-roles': 'error', 170 | 171 | // media elements must have captions 172 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md 173 | 'jsx-a11y/media-has-caption': ['error', { 174 | audio: [], 175 | video: [], 176 | track: [], 177 | }], 178 | 179 | // WAI-ARIA roles should not be used to convert an interactive element to non-interactive 180 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md 181 | 'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', { 182 | tr: ['none', 'presentation'], 183 | }], 184 | 185 | // WAI-ARIA roles should not be used to convert a non-interactive element to interactive 186 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md 187 | 'jsx-a11y/no-noninteractive-element-to-interactive-role': ['error', { 188 | ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 189 | ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 190 | li: ['menuitem', 'option', 'row', 'tab', 'treeitem'], 191 | table: ['grid'], 192 | td: ['gridcell'], 193 | }], 194 | 195 | // Tab key navigation should be limited to elements on the page that can be interacted with. 196 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md 197 | 'jsx-a11y/no-noninteractive-tabindex': ['error', { 198 | tags: [], 199 | roles: ['tabpanel'], 200 | }], 201 | 202 | // ensure tags are valid 203 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md 204 | 'jsx-a11y/anchor-is-valid': ['error', { 205 | components: ['Link'], 206 | specialLink: ['to'], 207 | aspects: ['noHref', 'invalidHref', 'preferButton'], 208 | }], 209 | }, 210 | }; 211 | -------------------------------------------------------------------------------- /css-in-javascript/README.md: -------------------------------------------------------------------------------- 1 | # Airbnb CSS-in-JavaScript Style Guide 2 | 3 | *A mostly reasonable approach to CSS-in-JavaScript* 4 | 5 | ## Table of Contents 6 | 7 | 1. [Naming](#naming) 8 | 1. [Ordering](#ordering) 9 | 1. [Nesting](#nesting) 10 | 1. [Inline](#inline) 11 | 1. [Themes](#themes) 12 | 13 | ## Naming 14 | 15 | - Use camelCase for object keys (i.e. "selectors"). 16 | 17 | > Why? We access these keys as properties on the `styles` object in the component, so it is most convenient to use camelCase. 18 | 19 | ```js 20 | // bad 21 | { 22 | 'bermuda-triangle': { 23 | display: 'none', 24 | }, 25 | } 26 | 27 | // good 28 | { 29 | bermudaTriangle: { 30 | display: 'none', 31 | }, 32 | } 33 | ``` 34 | 35 | - Use an underscore for modifiers to other styles. 36 | 37 | > Why? Similar to BEM, this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes. 38 | 39 | ```js 40 | // bad 41 | { 42 | bruceBanner: { 43 | color: 'pink', 44 | transition: 'color 10s', 45 | }, 46 | 47 | bruceBannerTheHulk: { 48 | color: 'green', 49 | }, 50 | } 51 | 52 | // good 53 | { 54 | bruceBanner: { 55 | color: 'pink', 56 | transition: 'color 10s', 57 | }, 58 | 59 | bruceBanner_theHulk: { 60 | color: 'green', 61 | }, 62 | } 63 | ``` 64 | 65 | - Use `selectorName_fallback` for sets of fallback styles. 66 | 67 | > Why? Similar to modifiers, keeping the naming consistent helps reveal the relationship of these styles to the styles that override them in more adequate browsers. 68 | 69 | ```js 70 | // bad 71 | { 72 | muscles: { 73 | display: 'flex', 74 | }, 75 | 76 | muscles_sadBears: { 77 | width: '100%', 78 | }, 79 | } 80 | 81 | // good 82 | { 83 | muscles: { 84 | display: 'flex', 85 | }, 86 | 87 | muscles_fallback: { 88 | width: '100%', 89 | }, 90 | } 91 | ``` 92 | 93 | - Use a separate selector for sets of fallback styles. 94 | 95 | > Why? Keeping fallback styles contained in a separate object clarifies their purpose, which improves readability. 96 | 97 | ```js 98 | // bad 99 | { 100 | muscles: { 101 | display: 'flex', 102 | }, 103 | 104 | left: { 105 | flexGrow: 1, 106 | display: 'inline-block', 107 | }, 108 | 109 | right: { 110 | display: 'inline-block', 111 | }, 112 | } 113 | 114 | // good 115 | { 116 | muscles: { 117 | display: 'flex', 118 | }, 119 | 120 | left: { 121 | flexGrow: 1, 122 | }, 123 | 124 | left_fallback: { 125 | display: 'inline-block', 126 | }, 127 | 128 | right_fallback: { 129 | display: 'inline-block', 130 | }, 131 | } 132 | ``` 133 | 134 | - Use device-agnostic names (e.g. "small", "medium", and "large") to name media query breakpoints. 135 | 136 | > Why? Commonly used names like "phone", "tablet", and "desktop" do not match the characteristics of the devices in the real world. Using these names sets the wrong expectations. 137 | 138 | ```js 139 | // bad 140 | const breakpoints = { 141 | mobile: '@media (max-width: 639px)', 142 | tablet: '@media (max-width: 1047px)', 143 | desktop: '@media (min-width: 1048px)', 144 | }; 145 | 146 | // good 147 | const breakpoints = { 148 | small: '@media (max-width: 639px)', 149 | medium: '@media (max-width: 1047px)', 150 | large: '@media (min-width: 1048px)', 151 | }; 152 | ``` 153 | 154 | ## Ordering 155 | 156 | - Define styles after the component. 157 | 158 | > Why? We use a higher-order component to theme our styles, which is naturally used after the component definition. Passing the styles object directly to this function reduces indirection. 159 | 160 | ```jsx 161 | // bad 162 | const styles = { 163 | container: { 164 | display: 'inline-block', 165 | }, 166 | }; 167 | 168 | function MyComponent({ styles }) { 169 | return ( 170 |
171 | Never doubt that a small group of thoughtful, committed citizens can 172 | change the world. Indeed, it’s the only thing that ever has. 173 |
174 | ); 175 | } 176 | 177 | export default withStyles(() => styles)(MyComponent); 178 | 179 | // good 180 | function MyComponent({ styles }) { 181 | return ( 182 |
183 | Never doubt that a small group of thoughtful, committed citizens can 184 | change the world. Indeed, it’s the only thing that ever has. 185 |
186 | ); 187 | } 188 | 189 | export default withStyles(() => ({ 190 | container: { 191 | display: 'inline-block', 192 | }, 193 | }))(MyComponent); 194 | ``` 195 | 196 | ## Nesting 197 | 198 | - Leave a blank line between adjacent blocks at the same indentation level. 199 | 200 | > Why? The whitespace improves readability and reduces the likelihood of merge conflicts. 201 | 202 | ```js 203 | // bad 204 | { 205 | bigBang: { 206 | display: 'inline-block', 207 | '::before': { 208 | content: "''", 209 | }, 210 | }, 211 | universe: { 212 | border: 'none', 213 | }, 214 | } 215 | 216 | // good 217 | { 218 | bigBang: { 219 | display: 'inline-block', 220 | 221 | '::before': { 222 | content: "''", 223 | }, 224 | }, 225 | 226 | universe: { 227 | border: 'none', 228 | }, 229 | } 230 | ``` 231 | 232 | ## Inline 233 | 234 | - Use inline styles for styles that have a high cardinality (e.g. uses the value of a prop) and not for styles that have a low cardinality. 235 | 236 | > Why? Generating themed stylesheets can be expensive, so they are best for discrete sets of styles. 237 | 238 | ```jsx 239 | // bad 240 | export default function MyComponent({ spacing }) { 241 | return ( 242 |
243 | ); 244 | } 245 | 246 | // good 247 | function MyComponent({ styles, spacing }) { 248 | return ( 249 |
250 | ); 251 | } 252 | export default withStyles(() => ({ 253 | periodic: { 254 | display: 'table', 255 | }, 256 | }))(MyComponent); 257 | ``` 258 | 259 | ## Themes 260 | 261 | - Use an abstraction layer such as [react-with-styles](https://github.com/airbnb/react-with-styles) that enables theming. *react-with-styles gives us things like `withStyles()`, `ThemedStyleSheet`, and `css()` which are used in some of the examples in this document.* 262 | 263 | > Why? It is useful to have a set of shared variables for styling your components. Using an abstraction layer makes this more convenient. Additionally, this can help prevent your components from being tightly coupled to any particular underlying implementation, which gives you more freedom. 264 | 265 | - Define colors only in themes. 266 | 267 | ```js 268 | // bad 269 | export default withStyles(() => ({ 270 | chuckNorris: { 271 | color: '#bada55', 272 | }, 273 | }))(MyComponent); 274 | 275 | // good 276 | export default withStyles(({ color }) => ({ 277 | chuckNorris: { 278 | color: color.badass, 279 | }, 280 | }))(MyComponent); 281 | ``` 282 | 283 | - Define fonts only in themes. 284 | 285 | ```js 286 | // bad 287 | export default withStyles(() => ({ 288 | towerOfPisa: { 289 | fontStyle: 'italic', 290 | }, 291 | }))(MyComponent); 292 | 293 | // good 294 | export default withStyles(({ font }) => ({ 295 | towerOfPisa: { 296 | fontStyle: font.italic, 297 | }, 298 | }))(MyComponent); 299 | ``` 300 | 301 | - Define fonts as sets of related styles. 302 | 303 | ```js 304 | // bad 305 | export default withStyles(() => ({ 306 | towerOfPisa: { 307 | fontFamily: 'Italiana, "Times New Roman", serif', 308 | fontSize: '2em', 309 | fontStyle: 'italic', 310 | lineHeight: 1.5, 311 | }, 312 | }))(MyComponent); 313 | 314 | // good 315 | export default withStyles(({ font }) => ({ 316 | towerOfPisa: { 317 | ...font.italian, 318 | }, 319 | }))(MyComponent); 320 | ``` 321 | 322 | - Define base grid units in theme (either as a value or a function that takes a multiplier). 323 | 324 | ```js 325 | // bad 326 | export default withStyles(() => ({ 327 | rip: { 328 | bottom: '-6912px', // 6 feet 329 | }, 330 | }))(MyComponent); 331 | 332 | // good 333 | export default withStyles(({ units }) => ({ 334 | rip: { 335 | bottom: units(864), // 6 feet, assuming our unit is 8px 336 | }, 337 | }))(MyComponent); 338 | 339 | // good 340 | export default withStyles(({ unit }) => ({ 341 | rip: { 342 | bottom: 864 * unit, // 6 feet, assuming our unit is 8px 343 | }, 344 | }))(MyComponent); 345 | ``` 346 | 347 | - Define media queries only in themes. 348 | 349 | ```js 350 | // bad 351 | export default withStyles(() => ({ 352 | container: { 353 | width: '100%', 354 | 355 | '@media (max-width: 1047px)': { 356 | width: '50%', 357 | }, 358 | }, 359 | }))(MyComponent); 360 | 361 | // good 362 | export default withStyles(({ breakpoint }) => ({ 363 | container: { 364 | width: '100%', 365 | 366 | [breakpoint.medium]: { 367 | width: '50%', 368 | }, 369 | }, 370 | }))(MyComponent); 371 | ``` 372 | 373 | - Define tricky fallback properties in themes. 374 | 375 | > Why? Many CSS-in-JavaScript implementations merge style objects together which makes specifying fallbacks for the same property (e.g. `display`) a little tricky. To keep the approach unified, put these fallbacks in the theme. 376 | 377 | ```js 378 | // bad 379 | export default withStyles(() => ({ 380 | .muscles { 381 | display: 'flex', 382 | }, 383 | 384 | .muscles_fallback { 385 | 'display ': 'table', 386 | }, 387 | }))(MyComponent); 388 | 389 | // good 390 | export default withStyles(({ fallbacks }) => ({ 391 | .muscles { 392 | display: 'flex', 393 | }, 394 | 395 | .muscles_fallback { 396 | [fallbacks.display]: 'table', 397 | }, 398 | }))(MyComponent); 399 | 400 | // good 401 | export default withStyles(({ fallback }) => ({ 402 | .muscles { 403 | display: 'flex', 404 | }, 405 | 406 | .muscles_fallback { 407 | [fallback('display')]: 'table', 408 | }, 409 | }))(MyComponent); 410 | ``` 411 | 412 | - Create as few custom themes as possible. Many applications may only have one theme. 413 | 414 | - Namespace custom theme settings under a nested object with a unique and descriptive key. 415 | 416 | ```js 417 | // bad 418 | ThemedStyleSheet.registerTheme('mySection', { 419 | mySectionPrimaryColor: 'green', 420 | }); 421 | 422 | // good 423 | ThemedStyleSheet.registerTheme('mySection', { 424 | mySection: { 425 | primaryColor: 'green', 426 | }, 427 | }); 428 | ``` 429 | 430 | --- 431 | 432 | CSS puns adapted from [Saijo George](https://saijogeorge.com/css-puns/). 433 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/imports.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true 4 | }, 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | sourceType: 'module' 8 | }, 9 | plugins: [ 10 | 'import' 11 | ], 12 | 13 | settings: { 14 | 'import/resolver': { 15 | node: { 16 | extensions: ['.mjs', '.js', '.json'] 17 | } 18 | }, 19 | 'import/extensions': [ 20 | '.js', 21 | '.mjs', 22 | '.jsx', 23 | ], 24 | 'import/core-modules': [ 25 | ], 26 | 'import/ignore': [ 27 | 'node_modules', 28 | '\\.(coffee|scss|css|less|hbs|svg|json)$', 29 | ], 30 | }, 31 | 32 | rules: { 33 | // Static analysis: 34 | 35 | // ensure imports point to files/modules that can be resolved 36 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md 37 | 'import/no-unresolved': ['error', { commonjs: true, caseSensitive: true }], 38 | 39 | // ensure named imports coupled with named exports 40 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it 41 | 'import/named': 'error', 42 | 43 | // ensure default import coupled with default export 44 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it 45 | 'import/default': 'off', 46 | 47 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md 48 | 'import/namespace': 'off', 49 | 50 | // Helpful warnings: 51 | 52 | // disallow invalid exports, e.g. multiple defaults 53 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md 54 | 'import/export': 'error', 55 | 56 | // do not allow a default import name to match a named export 57 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md 58 | 'import/no-named-as-default': 'error', 59 | 60 | // warn on accessing default export property names that are also named exports 61 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md 62 | 'import/no-named-as-default-member': 'error', 63 | 64 | // disallow use of jsdoc-marked-deprecated imports 65 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md 66 | 'import/no-deprecated': 'off', 67 | 68 | // Forbid the use of extraneous packages 69 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md 70 | // paths are treated both as absolute paths, and relative to process.cwd() 71 | 'import/no-extraneous-dependencies': ['error', { 72 | devDependencies: [ 73 | 'test/**', // tape, common npm pattern 74 | 'tests/**', // also common npm pattern 75 | 'spec/**', // mocha, rspec-like pattern 76 | '**/__tests__/**', // jest pattern 77 | '**/__mocks__/**', // jest pattern 78 | 'test.{js,jsx}', // repos with a single test file 79 | 'test-*.{js,jsx}', // repos with multiple top-level test files 80 | '**/*{.,_}{test,spec}.{js,jsx}', // tests where the extension or filename suffix denotes that it is a test 81 | '**/jest.config.js', // jest config 82 | '**/jest.setup.js', // jest setup 83 | '**/vue.config.js', // vue-cli config 84 | '**/webpack.config.js', // webpack config 85 | '**/webpack.config.*.js', // webpack config 86 | '**/rollup.config.js', // rollup config 87 | '**/rollup.config.*.js', // rollup config 88 | '**/gulpfile.js', // gulp config 89 | '**/gulpfile.*.js', // gulp config 90 | '**/Gruntfile{,.js}', // grunt config 91 | '**/protractor.conf.js', // protractor config 92 | '**/protractor.conf.*.js', // protractor config 93 | ], 94 | optionalDependencies: false, 95 | }], 96 | 97 | // Forbid mutable exports 98 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md 99 | 'import/no-mutable-exports': 'error', 100 | 101 | // Module systems: 102 | 103 | // disallow require() 104 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md 105 | 'import/no-commonjs': 'off', 106 | 107 | // disallow AMD require/define 108 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md 109 | 'import/no-amd': 'error', 110 | 111 | // No Node.js builtin modules 112 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md 113 | // TODO: enable? 114 | 'import/no-nodejs-modules': 'off', 115 | 116 | // Style guide: 117 | 118 | // disallow non-import statements appearing before import statements 119 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md 120 | 'import/first': 'error', 121 | 122 | // disallow non-import statements appearing before import statements 123 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md 124 | // deprecated: use `import/first` 125 | 'import/imports-first': 'off', 126 | 127 | // disallow duplicate imports 128 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 129 | 'import/no-duplicates': 'error', 130 | 131 | // disallow namespace imports 132 | // TODO: enable? 133 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md 134 | 'import/no-namespace': 'off', 135 | 136 | // Ensure consistent use of file extension within the import path 137 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md 138 | 'import/extensions': ['error', 'ignorePackages', { 139 | js: 'never', 140 | mjs: 'never', 141 | jsx: 'never', 142 | }], 143 | 144 | // ensure absolute imports are above relative imports and that unassigned imports are ignored 145 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md 146 | // TODO: enforce a stricter convention in module import order? 147 | 'import/order': ['error', { groups: [['builtin', 'external', 'internal']] }], 148 | 149 | // Require a newline after the last import/require in a group 150 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md 151 | 'import/newline-after-import': 'error', 152 | 153 | // Require modules with a single export to use a default export 154 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md 155 | 'import/prefer-default-export': 'error', 156 | 157 | // Restrict which files can be imported in a given folder 158 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md 159 | 'import/no-restricted-paths': 'off', 160 | 161 | // Forbid modules to have too many dependencies 162 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md 163 | 'import/max-dependencies': ['off', { max: 10 }], 164 | 165 | // Forbid import of modules using absolute paths 166 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md 167 | 'import/no-absolute-path': 'error', 168 | 169 | // Forbid require() calls with expressions 170 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md 171 | 'import/no-dynamic-require': 'error', 172 | 173 | // prevent importing the submodules of other modules 174 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md 175 | 'import/no-internal-modules': ['off', { 176 | allow: [], 177 | }], 178 | 179 | // Warn if a module could be mistakenly parsed as a script by a consumer 180 | // leveraging Unambiguous JavaScript Grammar 181 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/unambiguous.md 182 | // this should not be enabled until this proposal has at least been *presented* to TC39. 183 | // At the moment, it's not a thing. 184 | 'import/unambiguous': 'off', 185 | 186 | // Forbid Webpack loader syntax in imports 187 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md 188 | 'import/no-webpack-loader-syntax': 'error', 189 | 190 | // Prevent unassigned imports 191 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md 192 | // importing for side effects is perfectly acceptable, if you need side effects. 193 | 'import/no-unassigned-import': 'off', 194 | 195 | // Prevent importing the default as if it were named 196 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-default.md 197 | 'import/no-named-default': 'error', 198 | 199 | // Reports if a module's default export is unnamed 200 | // https://github.com/benmosher/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md 201 | 'import/no-anonymous-default-export': ['off', { 202 | allowArray: false, 203 | allowArrowFunction: false, 204 | allowAnonymousClass: false, 205 | allowAnonymousFunction: false, 206 | allowLiteral: false, 207 | allowObject: false, 208 | }], 209 | 210 | // This rule enforces that all exports are declared at the bottom of the file. 211 | // https://github.com/benmosher/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md 212 | // TODO: enable? 213 | 'import/exports-last': 'off', 214 | 215 | // Reports when named exports are not grouped together in a single export declaration 216 | // or when multiple assignments to CommonJS module.exports or exports object are present 217 | // in a single file. 218 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md 219 | 'import/group-exports': 'off', 220 | 221 | // forbid default exports. this is a terrible rule, do not use it. 222 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md 223 | 'import/no-default-export': 'off', 224 | 225 | // Prohibit named exports. this is a terrible rule, do not use it. 226 | // https://github.com/benmosher/eslint-plugin-import/blob/1ec80fa35fa1819e2d35a70e68fb6a149fb57c5e/docs/rules/no-named-export.md 227 | 'import/no-named-export': 'off', 228 | 229 | // Forbid a module from importing itself 230 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md 231 | 'import/no-self-import': 'error', 232 | 233 | // Forbid cyclical dependencies between modules 234 | // https://github.com/benmosher/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md 235 | 'import/no-cycle': ['error', { maxDepth: Infinity }], 236 | 237 | // Ensures that there are no useless path segments 238 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/no-useless-path-segments.md 239 | 'import/no-useless-path-segments': 'error', 240 | 241 | // dynamic imports require a leading comment with a webpackChunkName 242 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/dynamic-import-chunkname.md 243 | 'import/dynamic-import-chunkname': ['off', { 244 | importFunctions: [], 245 | webpackChunknameFormat: '[0-9a-zA-Z-_/.]+', 246 | }], 247 | 248 | // Use this rule to prevent imports to folders in relative parent paths. 249 | // https://github.com/benmosher/eslint-plugin-import/blob/c34f14f67f077acd5a61b3da9c0b0de298d20059/docs/rules/no-relative-parent-imports.md 250 | 'import/no-relative-parent-imports': 'off', 251 | }, 252 | }; 253 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/best-practices.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // enforces getter/setter pairs in objects 4 | 'accessor-pairs': 'off', 5 | 6 | // enforces return statements in callbacks of array's methods 7 | // https://eslint.org/docs/rules/array-callback-return 8 | 'array-callback-return': ['error', { allowImplicit: true }], 9 | 10 | // treat var statements as if they were block scoped 11 | 'block-scoped-var': 'error', 12 | 13 | // specify the maximum cyclomatic complexity allowed in a program 14 | complexity: ['off', 11], 15 | 16 | // enforce that class methods use "this" 17 | // https://eslint.org/docs/rules/class-methods-use-this 18 | 'class-methods-use-this': ['error', { 19 | exceptMethods: [], 20 | }], 21 | 22 | // require return statements to either always or never specify values 23 | 'consistent-return': 'error', 24 | 25 | // specify curly brace conventions for all control statements 26 | curly: ['error', 'multi-line'], 27 | 28 | // require default case in switch statements 29 | 'default-case': ['error', { commentPattern: '^no default$' }], 30 | 31 | // encourages use of dot notation whenever possible 32 | 'dot-notation': ['error', { allowKeywords: true }], 33 | 34 | // enforces consistent newlines before or after dots 35 | // https://eslint.org/docs/rules/dot-location 36 | 'dot-location': ['error', 'property'], 37 | 38 | // require the use of === and !== 39 | // https://eslint.org/docs/rules/eqeqeq 40 | eqeqeq: ['error', 'always', { null: 'ignore' }], 41 | 42 | // make sure for-in loops have an if statement 43 | 'guard-for-in': 'error', 44 | 45 | // enforce a maximum number of classes per file 46 | // https://eslint.org/docs/rules/max-classes-per-file 47 | // TODO: semver-major (eslint 5): enable 48 | 'max-classes-per-file': ['off', 1], 49 | 50 | // disallow the use of alert, confirm, and prompt 51 | 'no-alert': 'warn', 52 | 53 | // disallow use of arguments.caller or arguments.callee 54 | 'no-caller': 'error', 55 | 56 | // disallow lexical declarations in case/default clauses 57 | // https://eslint.org/docs/rules/no-case-declarations.html 58 | 'no-case-declarations': 'error', 59 | 60 | // disallow division operators explicitly at beginning of regular expression 61 | // https://eslint.org/docs/rules/no-div-regex 62 | 'no-div-regex': 'off', 63 | 64 | // disallow else after a return in an if 65 | // https://eslint.org/docs/rules/no-else-return 66 | 'no-else-return': ['error', { allowElseIf: false }], 67 | 68 | // disallow empty functions, except for standalone funcs/arrows 69 | // https://eslint.org/docs/rules/no-empty-function 70 | 'no-empty-function': ['error', { 71 | allow: [ 72 | 'arrowFunctions', 73 | 'functions', 74 | 'methods', 75 | ] 76 | }], 77 | 78 | // disallow empty destructuring patterns 79 | // https://eslint.org/docs/rules/no-empty-pattern 80 | 'no-empty-pattern': 'error', 81 | 82 | // disallow comparisons to null without a type-checking operator 83 | 'no-eq-null': 'off', 84 | 85 | // disallow use of eval() 86 | 'no-eval': 'error', 87 | 88 | // disallow adding to native types 89 | 'no-extend-native': 'error', 90 | 91 | // disallow unnecessary function binding 92 | 'no-extra-bind': 'error', 93 | 94 | // disallow Unnecessary Labels 95 | // https://eslint.org/docs/rules/no-extra-label 96 | 'no-extra-label': 'error', 97 | 98 | // disallow fallthrough of case statements 99 | 'no-fallthrough': 'error', 100 | 101 | // disallow the use of leading or trailing decimal points in numeric literals 102 | 'no-floating-decimal': 'error', 103 | 104 | // disallow reassignments of native objects or read-only globals 105 | // https://eslint.org/docs/rules/no-global-assign 106 | 'no-global-assign': ['error', { exceptions: [] }], 107 | // deprecated in favor of no-global-assign 108 | 'no-native-reassign': 'off', 109 | 110 | // disallow implicit type conversions 111 | // https://eslint.org/docs/rules/no-implicit-coercion 112 | 'no-implicit-coercion': ['off', { 113 | boolean: false, 114 | number: true, 115 | string: true, 116 | allow: [], 117 | }], 118 | 119 | // disallow var and named functions in global scope 120 | // https://eslint.org/docs/rules/no-implicit-globals 121 | 'no-implicit-globals': 'off', 122 | 123 | // disallow use of eval()-like methods 124 | 'no-implied-eval': 'error', 125 | 126 | // disallow this keywords outside of classes or class-like objects 127 | 'no-invalid-this': 'off', 128 | 129 | // disallow usage of __iterator__ property 130 | 'no-iterator': 'error', 131 | 132 | // disallow use of labels for anything other then loops and switches 133 | 'no-labels': ['error', { allowLoop: false, allowSwitch: false }], 134 | 135 | // disallow unnecessary nested blocks 136 | 'no-lone-blocks': 'error', 137 | 138 | // disallow creation of functions within loops 139 | 'no-loop-func': 'error', 140 | 141 | // disallow magic numbers 142 | // https://eslint.org/docs/rules/no-magic-numbers 143 | 'no-magic-numbers': ['off', { 144 | ignore: [], 145 | ignoreArrayIndexes: true, 146 | enforceConst: true, 147 | detectObjects: false, 148 | }], 149 | 150 | // disallow use of multiple spaces 151 | 'no-multi-spaces': ['error', { 152 | ignoreEOLComments: false, 153 | }], 154 | 155 | // disallow use of multiline strings 156 | 'no-multi-str': 'error', 157 | 158 | // disallow use of new operator when not part of the assignment or comparison 159 | 'no-new': 'error', 160 | 161 | // disallow use of new operator for Function object 162 | 'no-new-func': 'error', 163 | 164 | // disallows creating new instances of String, Number, and Boolean 165 | 'no-new-wrappers': 'error', 166 | 167 | // disallow use of (old style) octal literals 168 | 'no-octal': 'error', 169 | 170 | // disallow use of octal escape sequences in string literals, such as 171 | // var foo = 'Copyright \251'; 172 | 'no-octal-escape': 'error', 173 | 174 | // disallow reassignment of function parameters 175 | // disallow parameter object manipulation except for specific exclusions 176 | // rule: https://eslint.org/docs/rules/no-param-reassign.html 177 | 'no-param-reassign': ['error', { 178 | props: true, 179 | ignorePropertyModificationsFor: [ 180 | 'acc', // for reduce accumulators 181 | 'accumulator', // for reduce accumulators 182 | 'e', // for e.returnvalue 183 | 'ctx', // for Koa routing 184 | 'req', // for Express requests 185 | 'request', // for Express requests 186 | 'res', // for Express responses 187 | 'response', // for Express responses 188 | '$scope', // for Angular 1 scopes 189 | ] 190 | }], 191 | 192 | // disallow usage of __proto__ property 193 | 'no-proto': 'error', 194 | 195 | // disallow declaring the same variable more then once 196 | 'no-redeclare': 'error', 197 | 198 | // disallow certain object properties 199 | // https://eslint.org/docs/rules/no-restricted-properties 200 | 'no-restricted-properties': ['error', { 201 | object: 'arguments', 202 | property: 'callee', 203 | message: 'arguments.callee is deprecated', 204 | }, { 205 | object: 'global', 206 | property: 'isFinite', 207 | message: 'Please use Number.isFinite instead', 208 | }, { 209 | object: 'self', 210 | property: 'isFinite', 211 | message: 'Please use Number.isFinite instead', 212 | }, { 213 | object: 'window', 214 | property: 'isFinite', 215 | message: 'Please use Number.isFinite instead', 216 | }, { 217 | object: 'global', 218 | property: 'isNaN', 219 | message: 'Please use Number.isNaN instead', 220 | }, { 221 | object: 'self', 222 | property: 'isNaN', 223 | message: 'Please use Number.isNaN instead', 224 | }, { 225 | object: 'window', 226 | property: 'isNaN', 227 | message: 'Please use Number.isNaN instead', 228 | }, { 229 | property: '__defineGetter__', 230 | message: 'Please use Object.defineProperty instead.', 231 | }, { 232 | property: '__defineSetter__', 233 | message: 'Please use Object.defineProperty instead.', 234 | }, { 235 | object: 'Math', 236 | property: 'pow', 237 | message: 'Use the exponentiation operator (**) instead.', 238 | }], 239 | 240 | // disallow use of assignment in return statement 241 | 'no-return-assign': ['error', 'always'], 242 | 243 | // disallow redundant `return await` 244 | 'no-return-await': 'error', 245 | 246 | // disallow use of `javascript:` urls. 247 | 'no-script-url': 'error', 248 | 249 | // disallow self assignment 250 | // https://eslint.org/docs/rules/no-self-assign 251 | // TODO: semver-major: props -> true 252 | 'no-self-assign': ['error', { 253 | props: false, 254 | }], 255 | 256 | // disallow comparisons where both sides are exactly the same 257 | 'no-self-compare': 'error', 258 | 259 | // disallow use of comma operator 260 | 'no-sequences': 'error', 261 | 262 | // restrict what can be thrown as an exception 263 | 'no-throw-literal': 'error', 264 | 265 | // disallow unmodified conditions of loops 266 | // https://eslint.org/docs/rules/no-unmodified-loop-condition 267 | 'no-unmodified-loop-condition': 'off', 268 | 269 | // disallow usage of expressions in statement position 270 | 'no-unused-expressions': ['error', { 271 | allowShortCircuit: false, 272 | allowTernary: false, 273 | allowTaggedTemplates: false, 274 | }], 275 | 276 | // disallow unused labels 277 | // https://eslint.org/docs/rules/no-unused-labels 278 | 'no-unused-labels': 'error', 279 | 280 | // disallow unnecessary .call() and .apply() 281 | 'no-useless-call': 'off', 282 | 283 | // Disallow unnecessary catch clauses 284 | // https://eslint.org/docs/rules/no-useless-catch 285 | // TODO: enable, semver-major 286 | 'no-useless-catch': 'off', 287 | 288 | // disallow useless string concatenation 289 | // https://eslint.org/docs/rules/no-useless-concat 290 | 'no-useless-concat': 'error', 291 | 292 | // disallow unnecessary string escaping 293 | // https://eslint.org/docs/rules/no-useless-escape 294 | 'no-useless-escape': 'error', 295 | 296 | // disallow redundant return; keywords 297 | // https://eslint.org/docs/rules/no-useless-return 298 | 'no-useless-return': 'error', 299 | 300 | // disallow use of void operator 301 | // https://eslint.org/docs/rules/no-void 302 | 'no-void': 'error', 303 | 304 | // disallow usage of configurable warning terms in comments: e.g. todo 305 | 'no-warning-comments': ['off', { terms: ['todo', 'fixme', 'xxx'], location: 'start' }], 306 | 307 | // disallow use of the with statement 308 | 'no-with': 'error', 309 | 310 | // require using Error objects as Promise rejection reasons 311 | // https://eslint.org/docs/rules/prefer-promise-reject-errors 312 | 'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }], 313 | 314 | // require use of the second argument for parseInt() 315 | radix: 'error', 316 | 317 | // require `await` in `async function` (note: this is a horrible rule that should never be used) 318 | // https://eslint.org/docs/rules/require-await 319 | 'require-await': 'off', 320 | 321 | // Enforce the use of u flag on RegExp 322 | // https://eslint.org/docs/rules/require-unicode-regexp 323 | 'require-unicode-regexp': 'off', 324 | 325 | // requires to declare all vars on top of their containing scope 326 | 'vars-on-top': 'error', 327 | 328 | // require immediate function invocation to be wrapped in parentheses 329 | // https://eslint.org/docs/rules/wrap-iife.html 330 | 'wrap-iife': ['error', 'outside', { functionPrototypeMethods: false }], 331 | 332 | // require or disallow Yoda conditions 333 | yoda: 'error' 334 | } 335 | }; 336 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 13.1.0 / 2018-08-13 2 | ================== 3 | - [new] add eslint v5 support (#1834) 4 | - [deps] update `eslint-plugin-import`, `eslint`, `babel-preset-airbnb`, `safe-publish-latest`, `eslint-find-rules` 5 | - [docs] fix typo in readme (#1855) 6 | - [new] update base ecmaVersion to 2018; remove deprecated experimentalObjectRestSpread option 7 | 8 | 13.0.0 / 2018-06-21 9 | ================== 10 | - [breaking] order of import statements is ignored for unassigned imports (#1782) 11 | - [breaking] enable `import/no-cycle`: warn on cyclical dependencies (#1779) 12 | - [breaking] Change import/no-self-import from "off" to "error" (#1770) 13 | - [breaking] Update `object-curly-newline` to match eslint 4.18.0 (#1761) 14 | - [breaking] enable `no-useless-path-segments` (#1743) 15 | - [breaking] Prevent line breaks before and after `=` (#1710) 16 | - [breaking] Add .mjs extension support (#1634) 17 | - [breaking] enable `implicit-arrow-linebreak` 18 | - [breaking] Enables `nonblock-statement-body-position` rule and adds link to guide (#1618) 19 | - [breaking] `no-mixed-operators`: only warn on `**` and `%` mixed with arithmetic operators; removes violation against mixing common math operators. (#1611) 20 | - [breaking] `import/named`: enable 21 | - [breaking] `lines-between-class-members`: set to “always” 22 | - [breaking] `no-else-return`: disallow else-if (#1595) 23 | - [breaking] Enables eslint rule for operator-linebreak 24 | - [new] Adds config entry point with only whitespace rules enabled (#1749, #1751) 25 | - [minor] only allow one newline at the end (#1794) 26 | - [patch] Adjust imports for vue-cli (#1809) 27 | - [patch] Allow devDependencies for `foo_spec.js` naming style (#1732) 28 | - [patch] `function-paren-newline`: change to "consistent" 29 | - [patch] avoid `__mocks__` `no-extraneous-dependencies` check (#1772) 30 | - [patch] Include 'accumulator' exception for `no-param-reassign` (#1768) 31 | - [patch] Set import/extensions to ignorePackages (#1652) 32 | - [patch] properly ignore indentation on jsx 33 | - [patch] `array-callback-return`: enable `allowImplicit` option (#1668) 34 | - [deps] update `eslint`, `eslint-plugin-import` 35 | - [dev deps] update `babel-preset-airbnb`, `tape`, `eslint-find-rules` 36 | - [meta] add ES2015-2018 in npm package keywords (#1587) 37 | - [meta] Add licenses to sub packages (#1746) 38 | - [docs] add `npx` shortcut (#1694) 39 | - [docs] Use HTTPS for links to ESLint documentation (#1628) 40 | - [tests] ensure all entry points parse 41 | 42 | 12.1.0 / 2017-10-16 43 | ================== 44 | - [deps] update `eslint` to `v4.9` 45 | 46 | 12.0.2 / 2017-10-05 47 | ================== 48 | - [deps] update `eslint` 49 | 50 | 12.0.1 / 2017-09-27 51 | ================== 52 | - [fix] ensure all JSX elements are ignored by `indent` (#1569) 53 | - [deps] update `eslint` 54 | 55 | 12.0.0 / 2017-09-02 56 | ================== 57 | - [deps] [breaking] require `eslint` v4 58 | - enable `function-paren-newline`, `for-direction`, `getter-return`, `no-compare-neg-zero`, `semi-style`, `object-curly-newline`, `no-buffer-constructor`, `no-restricted-globals`, `switch-colon-spacing`, `template-tag-spacing`, `prefer-promise-reject-errors`, `prefer-destructuring` 59 | - improve `indent`, `no-multi-spaces`, `no-trailing-spaces`, `no-underscore-dangle` 60 | - [breaking] move `comma-dangle` to Stylistic Issues (#1514) 61 | - [breaking] Rules prohibiting global isNaN, isFinite (#1477) 62 | - [patch] also disallow padding in classes and switches (#1403) 63 | - [patch] support Protractor config files in import/no-extraneous-dependencies (#1543) 64 | 65 | 11.3.2 / 2017-08-22 66 | ================== 67 | - [patch] Add jest.config.js to import/no-extraneous-dependencies devDeps (#1522) 68 | - [patch] Improve Gruntfile glob pattern (#1503) 69 | - [deps] update `eslint` v4, `tape` 70 | - [docs] Specify yarn-specific install instructions (#1511) 71 | 72 | 11.3.1 / 2017-07-24 73 | ================== 74 | - [fix] `legacy`: remove top-level `ecmaFeatures` 75 | 76 | 11.3.0 / 2017-07-23 77 | ================== 78 | - [deps] allow eslint v3 or v4 (#1447) 79 | - [deps] update `eslint-plugin-import` 80 | - [minor] Balanced spacing for inline block comments (#1440) 81 | - [minor] `no-return-assign`: strengthen linting against returning assignments 82 | - [patch] Allow jsx extensions for test files (#1427) 83 | - [patch] `no-restricted-globals`: add confusing globals; leave disabled for now (#1420) 84 | - [patch] Support Protractor config files in import/no-extraneous-dependencies (#1456) 85 | - [docs] Remove TODO in prefer-reflect as it's deprecated (#1452) 86 | - [docs] add yarn instructions (#1463, #1464) 87 | 88 | 11.2.0 / 2017-05-14 89 | ================== 90 | - [minor] Disallow unused global variables 91 | 92 | 11.1.3 / 2017-04-03 93 | ================== 94 | - [patch] add error messages to `no-restricted-syntax` (#1353) 95 | - [deps] update `eslint` 96 | 97 | 11.1.2 / 2017-03-25 98 | ================== 99 | - [patch] `no-param-reassign`: add ignorePropertyModificationsFor (#1325) 100 | - [deps] update `eslint` 101 | 102 | 11.1.1 / 2017-03-03 103 | ================== 104 | - [deps] update `eslint` 105 | - [patch] enable `ignoreRestSiblings` in `no-unused-vars` 106 | 107 | 11.1.0 / 2017-01-08 108 | ================== 109 | - [minor] enable `no-multi-assign` 110 | - [deps] update `eslint`, `babel-preset-airbnb` 111 | - Update a deprecated option (`eqeqeq`) (#1244) 112 | 113 | 11.0.1 / 2017-01-08 114 | ================== 115 | - [deps] update `eslint` 116 | - [docs] add note about `install-peerdeps` (#1234) 117 | - [docs] Updated instructions to support non-bash users (#1214) 118 | 119 | 11.0.0 / 2016-12-11 120 | ================== 121 | - [breaking] enable `no-await-in-loop` 122 | - [patch] disable `no-duplicate-imports` rule (#1188, #1195, #1054) 123 | - [patch] `import/no-extraneous-dependencies`: add some comments to ignore patterns 124 | - [patch] add `import/no-extraneous-dependencies` ignore patterns for test files (#1174) 125 | - [patch] `import/no-extraneous-dependencies`: added ignore patterns for config files (#1168) 126 | - [deps] update `eslint`, `eslint-plugin-import`, `tape` 127 | 128 | 10.0.1 / 2016-11-07 129 | ================== 130 | - [fix] legacy config should not require `**` 131 | 132 | 10.0.0 / 2016-11-06 133 | ================== 134 | - [breaking] prefer `**` over `Math.pow` 135 | - [breaking] `comma-dangle`: require trailing commas for functions 136 | - [breaking] enable `no-useless-return` 137 | - [breaking] tighten up `indent` 138 | - [breaking] tighten up `spaced-comment` 139 | - [breaking] enable `import/no-named-default` 140 | - [patch] loosen `max-len` with `ignoreRegExpLiterals` option 141 | - [patch] loosen `no-extraneous-dependencies` for test files (#959, #1089) 142 | - [deps] update `eslint`, `eslint-plugin-import` 143 | - [dev deps] update `eslint-find-rules` 144 | - [Tests] on `node` `v7` 145 | 146 | 9.0.0 / 2016-10-16 147 | ================== 148 | - [breaking] Add `ForOfStatement` to `no-restricted-syntax` (#1122, #1134) 149 | - [breaking] enable `import/no-webpack-loader-syntax` (#1123) 150 | - [breaking] [deps] update `eslint` to `v3.8.0` (#1132) 151 | - [breaking] [deps] update `eslint-plugin-import` to v2 (#1101) 152 | - [patch] `new-cap`: add immutable.js exceptions 153 | - [docs] ensure latest version of config is installed 154 | - [dev deps] update `babel-preset-airbnb`, `eslint`, `eslint-find-rules`, `tape`, `safe-publish-latest` 155 | 156 | 8.0.0 / 2016-09-24 157 | ================== 158 | - [breaking] enable rules: `no-restricted-properties`, `prefer-numeric-literals`, `lines-around-directive`, `import/extensions`, `import/no-absolute-path`, `import/no-dynamic-require` 159 | 160 | 7.2.0 / 2016-09-23 161 | ================== 162 | - [new] set `ecmaVersion` to 2017; enable object rest/spread; update `babel-preset-airbnb` 163 | - [patch] fix category of `no-restricted-properties` 164 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules`, `safe-publish-latest` 165 | 166 | 7.1.0 / 2016-09-11 167 | ================== 168 | - [minor] enable `arrow-parens` rule 169 | 170 | 7.0.1 / 2016-09-10 171 | ================== 172 | - [patch] loosen `max-len` by ignoring strings 173 | - [deps] update to `eslint` `v3.5.0` 174 | 175 | 7.0.0 / 2016-09-06 176 | ================== 177 | - [breaking] Add no-plusplus in style.js and added explanation in README (#1012) 178 | 179 | 6.0.0 / 2016-09-06 180 | ================== 181 | - [breaking] `valid-typeof`: enable `requireStringLiterals` option 182 | - [breaking] enable `class-methods-use-this` 183 | - [breaking] enable `symbol-description` 184 | - [breaking] enable `no-bitwise` 185 | - [breaking] enable `no-tabs` 186 | - [breaking] enable `func-call-spacing` 187 | - [breaking] enable `no-template-curly-in-string` 188 | - [patch] remove redundant `DebuggerStatement` from `no-restricted-syntax` (#1031) 189 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import` 190 | - Update `ecmaVersion` to `2016` 191 | 192 | 5.0.3 / 2016-08-21 193 | ================== 194 | - [fix] correct `import/extensions` list (#1013) 195 | - [refactor] Changed ESLint rule configs to use 'off', 'warn', and 'error' instead of numbers for better readability (#946) 196 | - [deps] update `eslint`, `eslint-plugin-react` 197 | 198 | 5.0.2 / 2016-08-12 199 | ================== 200 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import` 201 | - [tests] add `safe-publish-latest` to `prepublish` 202 | 203 | 5.0.1 / 2016-07-29 204 | ================== 205 | - [patch] `no-unused-expressions`: flesh out options 206 | - [deps] update `eslint` to `v3.2`, `eslint-plugin-import` to `v1.12` 207 | - [tests] improve prepublish script 208 | 209 | 5.0.0 / 2016-07-24 210 | ================== 211 | - [breaking] enable `import/newline-after-import` 212 | - [breaking] enable overlooked rules: `linebreak-style`, `new-parens`, `no-continue`, `no-lonely-if`, `operator-assignment`, `space-unary-ops`, `dot-location`, `no-extra-boolean-cast`, `no-this-before-super`, `require-yield`, `no-path-concat`, `no-label-var`, `no-void`, `constructor-super`, `prefer-spread`, `no-new-require`, `no-undef-init`, `no-unexpected-multiline` 213 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import`, `babel-tape-runner`; add `babel-preset-airbnb` 214 | - [patch] flesh out defaults: `jsx-quotes` 215 | - [docs] update the peer dep install command to dynamically look up the right version numbers when installing peer deps 216 | - [tests] fix prepublish scripts 217 | 218 | 4.0.2 / 2016-07-14 219 | ================== 220 | - [fix] repair accidental comma-dangle change 221 | 222 | 4.0.1 / 2016-07-14 (unpublished) 223 | ================== 224 | - [fix] Prevent trailing commas in the legacy config (#950) 225 | - [deps] update `eslint-plugin-import` 226 | 227 | 4.0.0 / 2016-07-02 228 | ================== 229 | - [breaking] [deps] update `eslint` to v3; drop support for < node 4 230 | - [breaking] enable `rest-spread-spacing` rule 231 | - [breaking] enable `no-mixed-operators` rule 232 | - [breaking] enable `import` rules: `no-named-as-default`, `no-named-as-default-member`, `no-extraneous-dependencies` 233 | - [breaking] enable `object-property-newline` rule 234 | - [breaking] enable `no-prototype-builtins` rule 235 | - [breaking] enable `no-useless-rename` rule 236 | - [breaking] enable `unicode-bom` rule 237 | - [breaking] Enforce proper generator star spacing (#887) 238 | - [breaking] Enable imports/imports-first rule (#882) 239 | - [breaking] re-order rules; put import rules in separate file (#881) 240 | - [patch] `newline-per-chained-call`: bump the limit to 4 241 | - [patch] `object-shorthand`: do not warn when the concise form would have a string literal as a name 242 | - [patch] Loosen `prefer-const` to not warn when the variable is “read” before being assigned to 243 | - [refactor] fix quoting of rule properties (#885) 244 | - [refactor] `quotes`: Use object option form rather than deprecated string form. 245 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules`, `tape` 246 | - [tests] Only run `eslint-find-rules` on prepublish, not in tests 247 | 248 | 3.0.1 / 2016-05-08 249 | ================== 250 | - [patch] re-disable `no-extra-parens` (#869, #867) 251 | 252 | 3.0.0 / 2016-05-07 253 | ================== 254 | - [breaking] enable `import/no-mutable-exports` 255 | - [breaking] enable `no-class-assign` rule, to pair with `no-func-assign` 256 | - [breaking] widen `no-extra-parens` to include everything, except `nestedBinaryExpressions` 257 | - [breaking] Re-enabling `newline-per-chained-call` (#748) 258 | - [minor] enable `import/no-amd` 259 | - [patch] enable `import/no-duplicates` 260 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules` 261 | 262 | 2.0.0 / 2016-04-29 263 | ================== 264 | - [breaking] enable `no-unsafe-finally` rule 265 | - [semver-minor] enable `no-useless-computed-key` rule 266 | - [deps] update `eslint`, `eslint-plugin-import` 267 | 268 | 1.0.4 / 2016-04-26 269 | ================== 270 | - [deps] update `eslint-find-rules`, `eslint-plugin-import` 271 | 272 | 1.0.3 / 2016-04-21 273 | ================== 274 | - [patch: loosen rules] Allow empty class/object methods 275 | 276 | 1.0.2 / 2016-04-20 277 | ================== 278 | - [patch: loosen rules] Allow `break` (#840) 279 | 280 | 1.0.1 / 2016-04-19 281 | ================== 282 | - [patch: loosen rules] Allow `== null` (#542) 283 | 284 | 1.0.0 / 2016-04-19 285 | ================== 286 | - Initial commmit; moved content over from `eslint-config-airbnb` package. 287 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/style.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // enforce line breaks after opening and before closing array brackets 4 | // https://eslint.org/docs/rules/array-bracket-newline 5 | // TODO: enable? semver-major 6 | 'array-bracket-newline': ['off', 'consistent'], // object option alternative: { multiline: true, minItems: 3 } 7 | 8 | // enforce line breaks between array elements 9 | // https://eslint.org/docs/rules/array-element-newline 10 | // TODO: enable? semver-major 11 | 'array-element-newline': ['off', { multiline: true, minItems: 3 }], 12 | 13 | // enforce spacing inside array brackets 14 | 'array-bracket-spacing': ['error', 'never'], 15 | 16 | // enforce spacing inside single-line blocks 17 | // https://eslint.org/docs/rules/block-spacing 18 | 'block-spacing': ['error', 'always'], 19 | 20 | // enforce one true brace style 21 | 'brace-style': ['error', '1tbs', { allowSingleLine: true }], 22 | 23 | // require camel case names 24 | // TODO: semver-major (eslint 5): add ignoreDestructuring: false option 25 | camelcase: ['error', { properties: 'never' }], 26 | 27 | // enforce or disallow capitalization of the first letter of a comment 28 | // https://eslint.org/docs/rules/capitalized-comments 29 | 'capitalized-comments': ['off', 'never', { 30 | line: { 31 | ignorePattern: '.*', 32 | ignoreInlineComments: true, 33 | ignoreConsecutiveComments: true, 34 | }, 35 | block: { 36 | ignorePattern: '.*', 37 | ignoreInlineComments: true, 38 | ignoreConsecutiveComments: true, 39 | }, 40 | }], 41 | 42 | // require trailing commas in multiline object literals 43 | 'comma-dangle': ['error', { 44 | arrays: 'always-multiline', 45 | objects: 'always-multiline', 46 | imports: 'always-multiline', 47 | exports: 'always-multiline', 48 | functions: 'always-multiline', 49 | }], 50 | 51 | // enforce spacing before and after comma 52 | 'comma-spacing': ['error', { before: false, after: true }], 53 | 54 | // enforce one true comma style 55 | 'comma-style': ['error', 'last', { 56 | exceptions: { 57 | ArrayExpression: false, 58 | ArrayPattern: false, 59 | ArrowFunctionExpression: false, 60 | CallExpression: false, 61 | FunctionDeclaration: false, 62 | FunctionExpression: false, 63 | ImportDeclaration: false, 64 | ObjectExpression: false, 65 | ObjectPattern: false, 66 | VariableDeclaration: false, 67 | NewExpression: false, 68 | } 69 | }], 70 | 71 | // disallow padding inside computed properties 72 | 'computed-property-spacing': ['error', 'never'], 73 | 74 | // enforces consistent naming when capturing the current execution context 75 | 'consistent-this': 'off', 76 | 77 | // enforce newline at the end of file, with no multiple empty lines 78 | 'eol-last': ['error', 'always'], 79 | 80 | // enforce spacing between functions and their invocations 81 | // https://eslint.org/docs/rules/func-call-spacing 82 | 'func-call-spacing': ['error', 'never'], 83 | 84 | // requires function names to match the name of the variable or property to which they are 85 | // assigned 86 | // https://eslint.org/docs/rules/func-name-matching 87 | // TODO: semver-major (eslint 5): add considerPropertyDescriptor: true 88 | 'func-name-matching': ['off', 'always', { 89 | includeCommonJSModuleExports: false 90 | }], 91 | 92 | // require function expressions to have a name 93 | // https://eslint.org/docs/rules/func-names 94 | 'func-names': 'warn', 95 | 96 | // enforces use of function declarations or expressions 97 | // https://eslint.org/docs/rules/func-style 98 | // TODO: enable 99 | 'func-style': ['off', 'expression'], 100 | 101 | // enforce consistent line breaks inside function parentheses 102 | // https://eslint.org/docs/rules/function-paren-newline 103 | 'function-paren-newline': ['error', 'consistent'], 104 | 105 | // Blacklist certain identifiers to prevent them being used 106 | // https://eslint.org/docs/rules/id-blacklist 107 | 'id-blacklist': 'off', 108 | 109 | // this option enforces minimum and maximum identifier lengths 110 | // (variable names, property names etc.) 111 | 'id-length': 'off', 112 | 113 | // require identifiers to match the provided regular expression 114 | 'id-match': 'off', 115 | 116 | // Enforce the location of arrow function bodies with implicit returns 117 | // https://eslint.org/docs/rules/implicit-arrow-linebreak 118 | 'implicit-arrow-linebreak': ['error', 'beside'], 119 | 120 | // this option sets a specific tab width for your code 121 | // https://eslint.org/docs/rules/indent 122 | indent: ['error', 2, { 123 | SwitchCase: 1, 124 | VariableDeclarator: 1, 125 | outerIIFEBody: 1, 126 | // MemberExpression: null, 127 | FunctionDeclaration: { 128 | parameters: 1, 129 | body: 1 130 | }, 131 | FunctionExpression: { 132 | parameters: 1, 133 | body: 1 134 | }, 135 | CallExpression: { 136 | arguments: 1 137 | }, 138 | ArrayExpression: 1, 139 | ObjectExpression: 1, 140 | ImportDeclaration: 1, 141 | flatTernaryExpressions: false, 142 | // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js 143 | ignoredNodes: ['JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'], 144 | ignoreComments: false 145 | }], 146 | 147 | // specify whether double or single quotes should be used in JSX attributes 148 | // https://eslint.org/docs/rules/jsx-quotes 149 | 'jsx-quotes': ['off', 'prefer-double'], 150 | 151 | // enforces spacing between keys and values in object literal properties 152 | 'key-spacing': ['error', { beforeColon: false, afterColon: true }], 153 | 154 | // require a space before & after certain keywords 155 | 'keyword-spacing': ['error', { 156 | before: true, 157 | after: true, 158 | overrides: { 159 | return: { after: true }, 160 | throw: { after: true }, 161 | case: { after: true } 162 | } 163 | }], 164 | 165 | // enforce position of line comments 166 | // https://eslint.org/docs/rules/line-comment-position 167 | // TODO: enable? 168 | 'line-comment-position': ['off', { 169 | position: 'above', 170 | ignorePattern: '', 171 | applyDefaultPatterns: true, 172 | }], 173 | 174 | // disallow mixed 'LF' and 'CRLF' as linebreaks 175 | // https://eslint.org/docs/rules/linebreak-style 176 | 'linebreak-style': ['error', 'unix'], 177 | 178 | // require or disallow an empty line between class members 179 | // https://eslint.org/docs/rules/lines-between-class-members 180 | 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: false }], 181 | 182 | // enforces empty lines around comments 183 | 'lines-around-comment': 'off', 184 | 185 | // require or disallow newlines around directives 186 | // https://eslint.org/docs/rules/lines-around-directive 187 | 'lines-around-directive': ['error', { 188 | before: 'always', 189 | after: 'always', 190 | }], 191 | 192 | // specify the maximum depth that blocks can be nested 193 | 'max-depth': ['off', 4], 194 | 195 | // specify the maximum length of a line in your program 196 | // https://eslint.org/docs/rules/max-len 197 | 'max-len': ['error', 100, 2, { 198 | ignoreUrls: true, 199 | ignoreComments: false, 200 | ignoreRegExpLiterals: true, 201 | ignoreStrings: true, 202 | ignoreTemplateLiterals: true, 203 | }], 204 | 205 | // specify the max number of lines in a file 206 | // https://eslint.org/docs/rules/max-lines 207 | 'max-lines': ['off', { 208 | max: 300, 209 | skipBlankLines: true, 210 | skipComments: true 211 | }], 212 | 213 | // enforce a maximum function length 214 | // https://eslint.org/docs/rules/max-lines-per-function 215 | 'max-lines-per-function': ['off', { 216 | max: 50, 217 | skipBlankLines: true, 218 | skipComments: true, 219 | IIFEs: true, 220 | }], 221 | 222 | // specify the maximum depth callbacks can be nested 223 | 'max-nested-callbacks': 'off', 224 | 225 | // limits the number of parameters that can be used in the function declaration. 226 | 'max-params': ['off', 3], 227 | 228 | // specify the maximum number of statement allowed in a function 229 | 'max-statements': ['off', 10], 230 | 231 | // restrict the number of statements per line 232 | // https://eslint.org/docs/rules/max-statements-per-line 233 | 'max-statements-per-line': ['off', { max: 1 }], 234 | 235 | // enforce a particular style for multiline comments 236 | // https://eslint.org/docs/rules/multiline-comment-style 237 | 'multiline-comment-style': ['off', 'starred-block'], 238 | 239 | // require multiline ternary 240 | // https://eslint.org/docs/rules/multiline-ternary 241 | // TODO: enable? 242 | 'multiline-ternary': ['off', 'never'], 243 | 244 | // require a capital letter for constructors 245 | 'new-cap': ['error', { 246 | newIsCap: true, 247 | newIsCapExceptions: [], 248 | capIsNew: false, 249 | capIsNewExceptions: ['Immutable.Map', 'Immutable.Set', 'Immutable.List'], 250 | }], 251 | 252 | // disallow the omission of parentheses when invoking a constructor with no arguments 253 | // https://eslint.org/docs/rules/new-parens 254 | 'new-parens': 'error', 255 | 256 | // allow/disallow an empty newline after var statement 257 | 'newline-after-var': 'off', 258 | 259 | // https://eslint.org/docs/rules/newline-before-return 260 | 'newline-before-return': 'off', 261 | 262 | // enforces new line after each method call in the chain to make it 263 | // more readable and easy to maintain 264 | // https://eslint.org/docs/rules/newline-per-chained-call 265 | 'newline-per-chained-call': ['error', { ignoreChainWithDepth: 4 }], 266 | 267 | // disallow use of the Array constructor 268 | 'no-array-constructor': 'error', 269 | 270 | // disallow use of bitwise operators 271 | // https://eslint.org/docs/rules/no-bitwise 272 | 'no-bitwise': 'error', 273 | 274 | // disallow use of the continue statement 275 | // https://eslint.org/docs/rules/no-continue 276 | 'no-continue': 'error', 277 | 278 | // disallow comments inline after code 279 | 'no-inline-comments': 'off', 280 | 281 | // disallow if as the only statement in an else block 282 | // https://eslint.org/docs/rules/no-lonely-if 283 | 'no-lonely-if': 'error', 284 | 285 | // disallow un-paren'd mixes of different operators 286 | // https://eslint.org/docs/rules/no-mixed-operators 287 | 'no-mixed-operators': ['error', { 288 | // the list of arthmetic groups disallows mixing `%` and `**` 289 | // with other arithmetic operators. 290 | groups: [ 291 | ['%', '**'], 292 | ['%', '+'], 293 | ['%', '-'], 294 | ['%', '*'], 295 | ['%', '/'], 296 | ['**', '+'], 297 | ['**', '-'], 298 | ['**', '*'], 299 | ['**', '/'], 300 | ['&', '|', '^', '~', '<<', '>>', '>>>'], 301 | ['==', '!=', '===', '!==', '>', '>=', '<', '<='], 302 | ['&&', '||'], 303 | ['in', 'instanceof'] 304 | ], 305 | allowSamePrecedence: false 306 | }], 307 | 308 | // disallow mixed spaces and tabs for indentation 309 | 'no-mixed-spaces-and-tabs': 'error', 310 | 311 | // disallow use of chained assignment expressions 312 | // https://eslint.org/docs/rules/no-multi-assign 313 | 'no-multi-assign': ['error'], 314 | 315 | // disallow multiple empty lines and only one newline at the end 316 | 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }], 317 | 318 | // disallow negated conditions 319 | // https://eslint.org/docs/rules/no-negated-condition 320 | 'no-negated-condition': 'off', 321 | 322 | // disallow nested ternary expressions 323 | 'no-nested-ternary': 'error', 324 | 325 | // disallow use of the Object constructor 326 | 'no-new-object': 'error', 327 | 328 | // disallow use of unary operators, ++ and -- 329 | // https://eslint.org/docs/rules/no-plusplus 330 | 'no-plusplus': 'error', 331 | 332 | // disallow certain syntax forms 333 | // https://eslint.org/docs/rules/no-restricted-syntax 334 | 'no-restricted-syntax': [ 335 | 'error', 336 | { 337 | selector: 'ForInStatement', 338 | message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.', 339 | }, 340 | { 341 | selector: 'ForOfStatement', 342 | message: 'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', 343 | }, 344 | { 345 | selector: 'LabeledStatement', 346 | message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', 347 | }, 348 | { 349 | selector: 'WithStatement', 350 | message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', 351 | }, 352 | ], 353 | 354 | // disallow space between function identifier and application 355 | 'no-spaced-func': 'error', 356 | 357 | // disallow tab characters entirely 358 | 'no-tabs': 'error', 359 | 360 | // disallow the use of ternary operators 361 | 'no-ternary': 'off', 362 | 363 | // disallow trailing whitespace at the end of lines 364 | 'no-trailing-spaces': ['error', { 365 | skipBlankLines: false, 366 | ignoreComments: false, 367 | }], 368 | 369 | // disallow dangling underscores in identifiers 370 | // https://eslint.org/docs/rules/no-underscore-dangle 371 | 'no-underscore-dangle': ['error', { 372 | allow: [], 373 | allowAfterThis: false, 374 | allowAfterSuper: false, 375 | enforceInMethodNames: true, 376 | }], 377 | 378 | // disallow the use of Boolean literals in conditional expressions 379 | // also, prefer `a || b` over `a ? a : b` 380 | // https://eslint.org/docs/rules/no-unneeded-ternary 381 | 'no-unneeded-ternary': ['error', { defaultAssignment: false }], 382 | 383 | // disallow whitespace before properties 384 | // https://eslint.org/docs/rules/no-whitespace-before-property 385 | 'no-whitespace-before-property': 'error', 386 | 387 | // enforce the location of single-line statements 388 | // https://eslint.org/docs/rules/nonblock-statement-body-position 389 | 'nonblock-statement-body-position': ['error', 'beside', { overrides: {} }], 390 | 391 | // require padding inside curly braces 392 | 'object-curly-spacing': ['error', 'always'], 393 | 394 | // enforce line breaks between braces 395 | // https://eslint.org/docs/rules/object-curly-newline 396 | 'object-curly-newline': ['error', { 397 | ObjectExpression: { minProperties: 4, multiline: true, consistent: true }, 398 | ObjectPattern: { minProperties: 4, multiline: true, consistent: true }, 399 | ImportDeclaration: { minProperties: 4, multiline: true, consistent: true }, 400 | ExportDeclaration: { minProperties: 4, multiline: true, consistent: true }, 401 | }], 402 | 403 | // enforce "same line" or "multiple line" on object properties. 404 | // https://eslint.org/docs/rules/object-property-newline 405 | 'object-property-newline': ['error', { 406 | allowAllPropertiesOnSameLine: true, 407 | }], 408 | 409 | // allow just one var statement per function 410 | 'one-var': ['error', 'never'], 411 | 412 | // require a newline around variable declaration 413 | // https://eslint.org/docs/rules/one-var-declaration-per-line 414 | 'one-var-declaration-per-line': ['error', 'always'], 415 | 416 | // require assignment operator shorthand where possible or prohibit it entirely 417 | // https://eslint.org/docs/rules/operator-assignment 418 | 'operator-assignment': ['error', 'always'], 419 | 420 | // Requires operator at the beginning of the line in multiline statements 421 | // https://eslint.org/docs/rules/operator-linebreak 422 | 'operator-linebreak': ['error', 'before', { overrides: { '=': 'none' } }], 423 | 424 | // disallow padding within blocks 425 | 'padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never' }], 426 | 427 | // Require or disallow padding lines between statements 428 | // https://eslint.org/docs/rules/padding-line-between-statements 429 | 'padding-line-between-statements': 'off', 430 | 431 | // Prefer use of an object spread over Object.assign 432 | // https://eslint.org/docs/rules/prefer-object-spread 433 | // TODO: semver-major (eslint 5): enable 434 | 'prefer-object-spread': 'off', 435 | 436 | // require quotes around object literal property names 437 | // https://eslint.org/docs/rules/quote-props.html 438 | 'quote-props': ['error', 'as-needed', { keywords: false, unnecessary: true, numbers: false }], 439 | 440 | // specify whether double or single quotes should be used 441 | quotes: ['error', 'single', { avoidEscape: true }], 442 | 443 | // do not require jsdoc 444 | // https://eslint.org/docs/rules/require-jsdoc 445 | 'require-jsdoc': 'off', 446 | 447 | // require or disallow use of semicolons instead of ASI 448 | semi: ['error', 'always'], 449 | 450 | // enforce spacing before and after semicolons 451 | 'semi-spacing': ['error', { before: false, after: true }], 452 | 453 | // Enforce location of semicolons 454 | // https://eslint.org/docs/rules/semi-style 455 | 'semi-style': ['error', 'last'], 456 | 457 | // requires object keys to be sorted 458 | 'sort-keys': ['off', 'asc', { caseSensitive: false, natural: true }], 459 | 460 | // sort variables within the same declaration block 461 | 'sort-vars': 'off', 462 | 463 | // require or disallow space before blocks 464 | 'space-before-blocks': 'error', 465 | 466 | // require or disallow space before function opening parenthesis 467 | // https://eslint.org/docs/rules/space-before-function-paren 468 | 'space-before-function-paren': ['error', { 469 | anonymous: 'always', 470 | named: 'never', 471 | asyncArrow: 'always' 472 | }], 473 | 474 | // require or disallow spaces inside parentheses 475 | 'space-in-parens': ['error', 'never'], 476 | 477 | // require spaces around operators 478 | 'space-infix-ops': 'error', 479 | 480 | // Require or disallow spaces before/after unary operators 481 | // https://eslint.org/docs/rules/space-unary-ops 482 | 'space-unary-ops': ['error', { 483 | words: true, 484 | nonwords: false, 485 | overrides: { 486 | }, 487 | }], 488 | 489 | // require or disallow a space immediately following the // or /* in a comment 490 | // https://eslint.org/docs/rules/spaced-comment 491 | 'spaced-comment': ['error', 'always', { 492 | line: { 493 | exceptions: ['-', '+'], 494 | markers: ['=', '!'], // space here to support sprockets directives 495 | }, 496 | block: { 497 | exceptions: ['-', '+'], 498 | markers: ['=', '!'], // space here to support sprockets directives 499 | balanced: true, 500 | } 501 | }], 502 | 503 | // Enforce spacing around colons of switch statements 504 | // https://eslint.org/docs/rules/switch-colon-spacing 505 | 'switch-colon-spacing': ['error', { after: true, before: false }], 506 | 507 | // Require or disallow spacing between template tags and their literals 508 | // https://eslint.org/docs/rules/template-tag-spacing 509 | 'template-tag-spacing': ['error', 'never'], 510 | 511 | // require or disallow the Unicode Byte Order Mark 512 | // https://eslint.org/docs/rules/unicode-bom 513 | 'unicode-bom': ['error', 'never'], 514 | 515 | // require regex literals to be wrapped in parentheses 516 | 'wrap-regex': 'off' 517 | } 518 | }; 519 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 17.1.0 / 2018-08-13 2 | ================== 3 | - [new] add eslint v5 support 4 | - [minor] enable `label-has-associated-control` rule 5 | - [patch] re-enabling `jsx-one-expression-per-line` allowing single children, ignore DOM components on `jsx-no-bind` 6 | - [deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-react`, `eslint-plugin-import`, `safe-publish-latest`, `eslint-plugin-jsx-a11y`, `eslint-find-rules` 7 | - [docs] fix readme typo (#1855) 8 | 9 | 17.0.0 / 2018-06-21 10 | ================== 11 | - [breaking] update `eslint-config-airbnb-base` to v13 12 | - [breaking] enable `no-useless-path-segments` (#1743) 13 | - [breaking] update `eslint-plugin-react` to `v7.6`; update rule configs (#1737) 14 | - [breaking] bump react pragma to v16; update `class-methods-use-this`'s `exceptMethods` to include `componentDidCatch` (#1704) 15 | - [new] Adds config entry point with only whitespace rules enabled (#1749, #1751) 16 | - [patch] set `forbid-foreign-prop-types` to "warn" 17 | - [patch] Add new methods introduced in react@16.3 (#1831) 18 | - [patch] `label-has-for`: Remove redundant component (#1802) 19 | - [patch] Add 'to' as a specialLink to the 'anchor-is-valid' a11y rule (#1648) 20 | - [patch] disable `no-did-mount-set-state`, since it’s necessary for server-rendering. 21 | - [deps] update `eslint`, `eslint-plugin-react`, `eslint-plugin-import`, 22 | - [dev deps] update `babel-preset-airbnb`, `tape`, `eslint-find-rules` 23 | - [meta] add ES2015-2018 in npm package keywords (#1587) 24 | - [meta] Add licenses to sub packages (#1746) 25 | - [docs] add `npx` shortcut (#1694) 26 | - [docs] Use HTTPS for links to ESLint documentation (#1628) 27 | 28 | 16.1.0 / 2017-10-16 29 | ================== 30 | - [deps] update `eslint-config-airbnb-base`, `eslint` to v4.9 31 | 32 | 16.0.0 / 2017-10-06 33 | ================== 34 | - [breaking] [deps] require `eslint` `v4`, update `eslint-config-airbnb-base` 35 | - [breaking] [deps] Upgrade `eslint-plugin-jsx-a11y` to `v6`; enable more a11y rules (#1482) 36 | - [breaking] enable/add react rules: `react/jsx-curly-brace-presence`, `react/no-typos`, `react/no-unused-state`, `react/no-redundant-should-component-update`, `react/default-props-match-prop-types` 37 | - [new] add `propWrapperFunctions` default settings for `eslint-plugin-react` 38 | - [new] Enable `react/jsx-closing-tag-location` (#1533) 39 | - [deps] update `eslint` v4, `eslint-plugin-react`, `tape` 40 | - [docs] Specify yarn-specific install instructions (#1511) 41 | 42 | 15.1.0 / 2017-07-24 43 | ================== 44 | - [deps] allow eslint v3 or v4 (#1447) 45 | - [deps] update `eslint-plugin-import`, `eslint-config-airbnb-base` 46 | 47 | 15.0.2 / 2017-07-04 48 | ================== 49 | - [fix] jsx should be enabled via parserOptions, not via a root ecmaFeatures 50 | - [deps] update `babel-preset-airbnb`, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `tape` 51 | 52 | 15.0.1 / 2017-05-15 53 | ================== 54 | - [fix] set default React version to 15.0 (#1415) 55 | 56 | 15.0.0 / 2017-05-14 57 | ================== 58 | - [breaking] set default React version to 0.15 59 | - [breaking] `update eslint-plugin-jsx-a11y` to v5, enable new rules 60 | - [breaking] `update eslint-plugin-react` to v7, enable new rules 61 | - [minor] enable rules: `jsx-max-props-per-line`, `void-dom-elements-no-children` 62 | - [patch] Turn `ignorePureComponents` option on for react/prefer-stateless-function (#1378, #1398) 63 | - [deps] update `eslint`, `eslint-plugin-react`, `eslint-config-airbnb-base` 64 | 65 | 14.1.0 / 2017-02-05 66 | ================== 67 | - [patch] allow `eslint-plugin-jsx-a11y` to be v3 or v4. Remove `no-marquee` rule temporarily. 68 | - [deps] update `eslint-config-airbnb-base`, `babel-preset-airbnb`, `eslint` 69 | 70 | 14.0.0 / 2017-01-08 71 | ================== 72 | - [breaking] enable `react/no-array-index-key`, `react/require-default-props` 73 | - [breaking] [deps] update `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, `eslint-config-airbnb-base` 74 | - [breaking] [deps] update `eslint-plugin-jsx-a11y` to v3 (#1166) 75 | - [docs] add note about `install-peerdeps` (#1234) 76 | - [docs] Updated instructions to support non-bash users (#1214) 77 | 78 | 13.0.0 / 2016-11-06 79 | ================== 80 | - [breaking] Enable `import/no-webpack-loader-syntax` rule (#1123) 81 | - [patch] `class-methods-use-this`: exempt React `getChildContext` (#1094) 82 | - [patch] set `react/no-unused-prop-types` skipShapeProps (#1099) 83 | - [deps] [breaking] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-import` 84 | - [dev deps] update `babel-preset-airbnb`, `eslint`, `eslint-find-rules`, `tape`, `safe-publish-latest` 85 | - [Tests] on `node` `v7` 86 | - [docs] ensure latest version of config is installed (#1121) 87 | 88 | 12.0.0 / 2016-09-24 89 | ================== 90 | - [breaking] Enable react rules: `react/no-unescaped-entities`, `react/no-children-prop` 91 | - [breaking] [deps] update `eslint-config-airbnb-base` 92 | - [patch] disable deprecated and redundant `react/require-extension` rule (#978) 93 | 94 | 11.2.0 / 2016-09-23 95 | ================== 96 | - [new] set `ecmaVersion` to 2017; enable object rest/spread; update `babel-preset-airbnb` 97 | - [deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-find-rules`, `safe-publish-latest` 98 | 99 | 11.1.0 / 2016-09-11 100 | ================== 101 | - [deps] update `eslint-config-airbnb-base`, `eslint` 102 | 103 | 11.0.0 / 2016-09-08 104 | ================== 105 | - [breaking] enable `react` rules: `react/no-danger-with-children`, `react/no-unused-prop-types`, `react/style-prop-object`, `react/forbid-prop-types`, `react/jsx-no-duplicate-props`; set `react/no-danger` to “warn” 106 | - [breaking] enable `jsx-a11y` rules: `jsx-a11y/anchor-has-content`, `jsx-a11y/tabindex-no-positive`, `jsx-a11y/no-static-element-interactions` 107 | - [deps] update `eslint`, `eslint-plugin-react`, `eslint-config-airbnb-base`, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` 108 | - [patch] set `ignoreCase` to `true` in disabled rules. 109 | - [docs] use “#” in example command rather than version numbers (#984) 110 | 111 | 10.0.1 / 2016-08-12 112 | ================== 113 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-jsx-a11y`, `eslint-plugin-import`, `eslint-config-airbnb-base` 114 | 115 | 10.0.0 / 2016-08-01 116 | ================== 117 | - [breaking] enable jsx-a11y rules: 118 | - `jsx-a11y/heading-has-content` 119 | - `jsx-a11y/html-has-lang` 120 | - `jsx-a11y/lang` 121 | - `jsx-a11y/no-marquee` 122 | - `jsx-a11y/scope` 123 | - `jsx-a11y/href-no-hash` 124 | - `jsx-a11y/label-has-for` 125 | - [breaking] enable aria rules: 126 | - `jsx-a11y/aria-props` 127 | - `jsx-a11y/aria-proptypes` 128 | - `jsx-a11y/aria-unsupported-elements` 129 | - `jsx-a11y/role-has-required-aria-props` 130 | - `jsx-a11y/role-supports-aria-props` 131 | - [breaking] enable react rules: 132 | - `react/jsx-filename-extension` 133 | - `react/jsx-no-comment-textnodes` 134 | - `react/jsx-no-target-blank` 135 | - `react/require-extension` 136 | - `react/no-render-return-value` 137 | - `react/no-find-dom-node` 138 | - `react/no-deprecated` 139 | - [deps] [breaking] update `eslint` to v3, `eslint-config-airbnb-base` to v5, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` to v2, `eslint-plugin-react` to v6, `tape`. drop node < 4 support. 140 | - [deps] update `eslint-config-airbnb-base`, `eslint-plugin-react`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `babel-tape-runner`, add `babel-preset-airbnb`. ensure react is `>=` 0.13.0 141 | - [patch] loosen `jsx-pascal-case` rule to allow all caps component names 142 | - [tests] stop testing < node 4 143 | - [tests] use `in-publish` because coffeescript screwed up the prepublish script for everyone 144 | - [tests] Only run `eslint-find-rules` on prepublish, not in tests 145 | - [tests] Even though the base config may not be up to date in the main package, let’s `npm link` the base package into the main one for the sake of travis-ci tests 146 | - [docs] update the peer dep install command to dynamically look up the right version numbers when installing peer deps 147 | - add `safe-publish-latest` to `prepublish` 148 | 149 | 9.0.1 / 2016-05-08 150 | ================== 151 | - [patch] update `eslint-config-airbnb-base` to v3.0.1 152 | 153 | 9.0.0 / 2016-05-07 154 | ================== 155 | - [breaking] update `eslint-config-airbnb-base` to v3 156 | - [deps] update `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` 157 | 158 | 8.0.0 / 2016-04-21 159 | ================== 160 | - [breaking] Migrate non-React rules to a separate linter config (`eslint-config-airbnb-base`) 161 | - [breaking] disallow empty methods 162 | - [breaking] disallow empty restructuring patterns 163 | - [breaking] enable `no-restricted-syntax` rule 164 | - [breaking] enable `global-require` rule 165 | - [breaking] [react] enable `react/jsx-curly-spacing` rule ([#693](https://github.com/airbnb/javascript/issues/693)) 166 | - [semver-minor] [react] Add `react/jsx-first-prop-new-line` rule 167 | - [semver-minor] [react] enable `jsx-equals-spacing` rule 168 | - [semver-minor] [react] enable `jsx-indent` rule 169 | - [semver-minor] enforce spacing inside single-line blocks 170 | - [semver-minor] enforce `no-underscore-dangle` 171 | - [semver-minor] Enable import/no-unresolved and import/export rules ([#825](https://github.com/airbnb/javascript/issues/825)) 172 | - [semver-patch] Enable `no-useless-concat` rule which `prefer-template` already covers 173 | - [semver-patch] Allow `== null` ([#542](https://github.com/airbnb/javascript/issues/542)) 174 | - [dev deps / peer deps] update `eslint`, `eslint-plugin-react`, `eslint-plugin-import` 175 | - [dev deps / peer deps] update `eslint-plugin-jsx-a11y` and rename rules ([#838](https://github.com/airbnb/javascript/issues/838)) 176 | - [refactor] [react] separate a11y rules to their own file 177 | - [refactor] Add missing disabled rules. 178 | - [tests] Add `eslint-find-rules` to prevent missing rules 179 | 180 | 7.0.0 / 2016-04-11 181 | ================== 182 | - [react] [breaking] Add accessibility rules to the React style guide + `eslint-plugin-a11y` 183 | - [breaking] enable `react/require-render-return` 184 | - [breaking] Add `no-dupe-class-members` rule + section ([#785](https://github.com/airbnb/javascript/issues/785)) 185 | - [breaking] error on debugger statements 186 | - [breaking] add `no-useless-escape` rule 187 | - [breaking] add `no-duplicate-imports` rule 188 | - [semver-minor] enable `jsx-pascal-case` rule 189 | - [deps] update `eslint`, `react` 190 | - [dev deps] update `eslint`, `eslint-plugin-react` 191 | 192 | 6.2.0 / 2016-03-22 193 | ================== 194 | - [new] Allow arrow functions in JSX props 195 | - [fix] re-enable `no-confusing-arrow` rule, with `allowParens` option enabled ([#752](https://github.com/airbnb/javascript/issues/752), [#791](https://github.com/airbnb/javascript/issues/791)) 196 | - [dev deps] update `tape`, `eslint`, `eslint-plugin-react` 197 | - [peer deps] update `eslint`, `eslint-plugin-react` 198 | 199 | 6.1.0 / 2016-02-22 200 | ================== 201 | - [new] enable [`react/prefer-stateless-function`][react/prefer-stateless-function] 202 | - [dev deps] update `react-plugin-eslint`, `eslint`, `tape` 203 | 204 | 6.0.2 / 2016-02-22 205 | ================== 206 | - [fix] disable [`no-confusing-arrow`][no-confusing-arrow] due to an `eslint` bug ([#752](https://github.com/airbnb/javascript/issues/752)) 207 | 208 | 6.0.1 / 2016-02-21 209 | ================== 210 | - [fix] disable [`newline-per-chained-call`][newline-per-chained-call] due to an `eslint` bug ([#748](https://github.com/airbnb/javascript/issues/748)) 211 | 212 | 6.0.0 / 2016-02-21 213 | ================== 214 | - [breaking] enable [`array-callback-return`][array-callback-return] 215 | - [breaking] enable [`no-confusing-arrow`][no-confusing-arrow] 216 | - [breaking] enable [`no-new-symbol`][no-new-symbol] 217 | - [breaking] enable [`no-restricted-imports`][no-restricted-imports] 218 | - [breaking] enable [`no-useless-constructor`][no-useless-constructor] 219 | - [breaking] enable [`prefer-rest-params`][prefer-rest-params] 220 | - [breaking] enable [`template-curly-spacing`][template-curly-spacing] 221 | - [breaking] enable [`newline-per-chained-call`][newline-per-chained-call] 222 | - [breaking] enable [`one-var-declaration-per-line`][one-var-declaration-per-line] 223 | - [breaking] enable [`no-self-assign`][no-self-assign] 224 | - [breaking] enable [`no-whitespace-before-property`][no-whitespace-before-property] 225 | - [breaking] [react] enable [`react/jsx-space-before-closing`][react/jsx-space-before-closing] 226 | - [breaking] [react] enable `static-methods` at top of [`react/sort-comp`][react/sort-comp] 227 | - [breaking] [react] don't `ignoreTranspilerName` for [`react/display-name`][react/display-name] 228 | - [peer+dev deps] update `eslint`, `eslint-plugin-react` ([#730](https://github.com/airbnb/javascript/issues/730)) 229 | 230 | 5.0.1 / 2016-02-13 231 | ================== 232 | - [fix] `eslint` peerDep should not include breaking changes 233 | 234 | 5.0.0 / 2016-02-03 235 | ================== 236 | - [breaking] disallow unneeded ternary expressions 237 | - [breaking] Avoid lexical declarations in case/default clauses 238 | - [dev deps] update `babel-tape-runner`, `eslint-plugin-react`, `react`, `tape` 239 | 240 | 4.0.0 / 2016-01-22 241 | ================== 242 | - [breaking] require outer IIFE wrapping; flesh out guide section 243 | - [minor] Add missing [`arrow-body-style`][arrow-body-style], [`prefer-template`][prefer-template] rules ([#678](https://github.com/airbnb/javascript/issues/678)) 244 | - [minor] Add [`prefer-arrow-callback`][prefer-arrow-callback] to ES6 rules (to match the guide) ([#677](https://github.com/airbnb/javascript/issues/677)) 245 | - [Tests] run `npm run lint` as part of tests; fix errors 246 | - [Tests] use `parallelshell` to parallelize npm run-scripts 247 | 248 | 3.1.0 / 2016-01-07 249 | ================== 250 | - [minor] Allow multiple stateless components in a single file 251 | 252 | 3.0.2 / 2016-01-06 253 | ================== 254 | - [fix] Ignore URLs in [`max-len`][max-len] ([#664](https://github.com/airbnb/javascript/issues/664)) 255 | 256 | 3.0.1 / 2016-01-06 257 | ================== 258 | - [fix] because we use babel, keywords should not be quoted 259 | 260 | 3.0.0 / 2016-01-04 261 | ================== 262 | - [breaking] enable [`quote-props`][quote-props] rule ([#632](https://github.com/airbnb/javascript/issues/632)) 263 | - [breaking] Define a max line length of 100 characters ([#639](https://github.com/airbnb/javascript/issues/639)) 264 | - [breaking] [react] Minor cleanup for the React styleguide, add [`react/jsx-no-bind`][react/jsx-no-bind] ([#619](https://github.com/airbnb/javascript/issues/619)) 265 | - [breaking] update best-practices config to prevent parameter object manipulation ([#627](https://github.com/airbnb/javascript/issues/627)) 266 | - [minor] Enable [`react/no-is-mounted`][react/no-is-mounted] rule (#635, #633) 267 | - [minor] Sort [`react/prefer-es6-class`][react/prefer-es6-class] alphabetically ([#634](https://github.com/airbnb/javascript/issues/634)) 268 | - [minor] enable [`react/prefer-es6-class`][react/prefer-es6-class] rule 269 | - Permit strict mode in "legacy" config 270 | - [react] add missing rules from `eslint-plugin-react` (enforcing where necessary) ([#581](https://github.com/airbnb/javascript/issues/581)) 271 | - [dev deps] update `eslint-plugin-react` 272 | 273 | 2.1.1 / 2015-12-15 274 | ================== 275 | - [fix] Remove deprecated [`react/jsx-quotes`][react/jsx-quotes] ([#622](https://github.com/airbnb/javascript/issues/622)) 276 | 277 | 2.1.0 / 2015-12-15 278 | ================== 279 | - [fix] use `require.resolve` to allow nested `extend`s ([#582](https://github.com/airbnb/javascript/issues/582)) 280 | - [new] enable [`object-shorthand`][object-shorthand] rule ([#621](https://github.com/airbnb/javascript/issues/621)) 281 | - [new] enable [`arrow-spacing`][arrow-spacing] rule ([#517](https://github.com/airbnb/javascript/issues/517)) 282 | - [docs] flesh out react rule defaults ([#618](https://github.com/airbnb/javascript/issues/618)) 283 | 284 | 2.0.0 / 2015-12-03 285 | ================== 286 | - [breaking] [`space-before-function-paren`][space-before-function-paren]: require function spacing: `function (` ([#605](https://github.com/airbnb/javascript/issues/605)) 287 | - [breaking] [`indent`][indent]: Fix switch statement indentation rule ([#606](https://github.com/airbnb/javascript/issues/606)) 288 | - [breaking] [`array-bracket-spacing`][array-bracket-spacing], [`computed-property-spacing`][computed-property-spacing]: disallow spacing inside brackets ([#594](https://github.com/airbnb/javascript/issues/594)) 289 | - [breaking] [`object-curly-spacing`][object-curly-spacing]: require padding inside curly braces ([#594](https://github.com/airbnb/javascript/issues/594)) 290 | - [breaking] [`space-in-parens`][space-in-parens]: disallow spaces in parens ([#594](https://github.com/airbnb/javascript/issues/594)) 291 | 292 | 1.0.2 / 2015-11-25 293 | ================== 294 | - [breaking] [`no-multiple-empty-lines`][no-multiple-empty-lines]: only allow 1 blank line at EOF ([#578](https://github.com/airbnb/javascript/issues/578)) 295 | - [new] `restParams`: enable rest params ([#592](https://github.com/airbnb/javascript/issues/592)) 296 | 297 | 1.0.1 / 2015-11-25 298 | ================== 299 | - *erroneous publish* 300 | 301 | 1.0.0 / 2015-11-08 302 | ================== 303 | - require `eslint` `v1.0.0` or higher 304 | - remove `babel-eslint` dependency 305 | 306 | 0.1.1 / 2015-11-05 307 | ================== 308 | - remove [`id-length`][id-length] rule ([#569](https://github.com/airbnb/javascript/issues/569)) 309 | - enable [`no-mixed-spaces-and-tabs`][no-mixed-spaces-and-tabs] ([#539](https://github.com/airbnb/javascript/issues/539)) 310 | - enable [`no-const-assign`][no-const-assign] ([#560](https://github.com/airbnb/javascript/issues/560)) 311 | - enable [`space-before-keywords`][space-before-keywords] ([#554](https://github.com/airbnb/javascript/issues/554)) 312 | 313 | 0.1.0 / 2015-11-05 314 | ================== 315 | - switch to modular rules files courtesy the [eslint-config-default][ecd] project and [@taion][taion]. [PR][pr-modular] 316 | - export `eslint-config-airbnb/legacy` for ES5-only users. `eslint-config-airbnb/legacy` does not require the `babel-eslint` parser. [PR][pr-legacy] 317 | 318 | 0.0.9 / 2015-09-24 319 | ================== 320 | - add rule [`no-undef`][no-undef] 321 | - add rule [`id-length`][id-length] 322 | 323 | 0.0.8 / 2015-08-21 324 | ================== 325 | - now has a changelog 326 | - now is modular (see instructions above for with react and without react versions) 327 | 328 | 0.0.7 / 2015-07-30 329 | ================== 330 | - TODO: fill in 331 | 332 | 333 | [ecd]: https://github.com/walmartlabs/eslint-config-defaults 334 | [taion]: https://github.com/taion 335 | [pr-modular]: https://github.com/airbnb/javascript/pull/526 336 | [pr-legacy]: https://github.com/airbnb/javascript/pull/527 337 | 338 | [array-bracket-spacing]: https://eslint.org/docs/rules/array-bracket-spacing 339 | [array-callback-return]: https://eslint.org/docs/rules/array-callback-return 340 | [arrow-body-style]: https://eslint.org/docs/rules/arrow-body-style 341 | [arrow-spacing]: https://eslint.org/docs/rules/arrow-spacing 342 | [computed-property-spacing]: https://eslint.org/docs/rules/computed-property-spacing 343 | [id-length]: https://eslint.org/docs/rules/id-length 344 | [indent]: https://eslint.org/docs/rules/indent 345 | [max-len]: https://eslint.org/docs/rules/max-len 346 | [newline-per-chained-call]: https://eslint.org/docs/rules/newline-per-chained-call 347 | [no-confusing-arrow]: https://eslint.org/docs/rules/no-confusing-arrow 348 | [no-const-assign]: https://eslint.org/docs/rules/no-const-assign 349 | [no-mixed-spaces-and-tabs]: https://eslint.org/docs/rules/no-mixed-spaces-and-tabs 350 | [no-multiple-empty-lines]: https://eslint.org/docs/rules/no-multiple-empty-lines 351 | [no-new-symbol]: https://eslint.org/docs/rules/no-new-symbol 352 | [no-restricted-imports]: https://eslint.org/docs/rules/no-restricted-imports 353 | [no-self-assign]: https://eslint.org/docs/rules/no-self-assign 354 | [no-undef]: https://eslint.org/docs/rules/no-undef 355 | [no-useless-constructor]: https://eslint.org/docs/rules/no-useless-constructor 356 | [no-whitespace-before-property]: https://eslint.org/docs/rules/no-whitespace-before-property 357 | [object-curly-spacing]: https://eslint.org/docs/rules/object-curly-spacing 358 | [object-shorthand]: https://eslint.org/docs/rules/object-shorthand 359 | [one-var-declaration-per-line]: https://eslint.org/docs/rules/one-var-declaration-per-line 360 | [prefer-arrow-callback]: https://eslint.org/docs/rules/prefer-arrow-callback 361 | [prefer-rest-params]: https://eslint.org/docs/rules/prefer-rest-params 362 | [prefer-template]: https://eslint.org/docs/rules/prefer-template 363 | [quote-props]: https://eslint.org/docs/rules/quote-props 364 | [space-before-function-paren]: https://eslint.org/docs/rules/space-before-function-paren 365 | [space-before-keywords]: https://eslint.org/docs/rules/space-before-keywords 366 | [space-in-parens]: https://eslint.org/docs/rules/space-in-parens 367 | [template-curly-spacing]: https://eslint.org/docs/rules/template-curly-spacing 368 | 369 | [react/jsx-space-before-closing]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md 370 | [react/sort-comp]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md 371 | [react/display-name]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md 372 | [react/jsx-no-bind]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 373 | [react/no-is-mounted]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md 374 | [react/prefer-es6-class]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md 375 | [react/jsx-quotes]: https://github.com/yannickcr/eslint-plugin-react/blob/f817e37beddddc84b4788969f07c524fa7f0823b/docs/rules/jsx-quotes.md 376 | [react/prefer-stateless-function]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md 377 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/rules/react.js: -------------------------------------------------------------------------------- 1 | const assign = require('object.assign'); 2 | const baseStyleRules = require('eslint-config-airbnb-base/rules/style').rules; 3 | 4 | const dangleRules = baseStyleRules['no-underscore-dangle']; 5 | 6 | module.exports = { 7 | plugins: [ 8 | 'react', 9 | ], 10 | 11 | parserOptions: { 12 | ecmaFeatures: { 13 | jsx: true, 14 | }, 15 | }, 16 | 17 | // View link below for react rules documentation 18 | // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules 19 | rules: { 20 | 'no-underscore-dangle': [dangleRules[0], assign({}, dangleRules[1], { 21 | allow: dangleRules[1].allow.concat(['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']), 22 | })], 23 | 24 | // Specify whether double or single quotes should be used in JSX attributes 25 | // https://eslint.org/docs/rules/jsx-quotes 26 | 'jsx-quotes': ['error', 'prefer-double'], 27 | 28 | 'class-methods-use-this': ['error', { 29 | exceptMethods: [ 30 | 'render', 31 | 'getInitialState', 32 | 'getDefaultProps', 33 | 'getChildContext', 34 | 'componentWillMount', 35 | 'UNSAFE_componentWillMount', 36 | 'componentDidMount', 37 | 'componentWillReceiveProps', 38 | 'UNSAFE_componentWillReceiveProps', 39 | 'shouldComponentUpdate', 40 | 'componentWillUpdate', 41 | 'UNSAFE_componentWillUpdate', 42 | 'componentDidUpdate', 43 | 'componentWillUnmount', 44 | 'componentDidCatch', 45 | 'getSnapshotBeforeUpdate' 46 | ], 47 | }], 48 | 49 | // Prevent missing displayName in a React component definition 50 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md 51 | 'react/display-name': ['off', { ignoreTranspilerName: false }], 52 | 53 | // Forbid certain propTypes (any, array, object) 54 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-prop-types.md 55 | 'react/forbid-prop-types': ['error', { 56 | forbid: ['any', 'array', 'object'], 57 | checkContextTypes: true, 58 | checkChildContextTypes: true, 59 | }], 60 | 61 | // Forbid certain props on DOM Nodes 62 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-dom-props.md 63 | 'react/forbid-dom-props': ['off', { forbid: [] }], 64 | 65 | // Enforce boolean attributes notation in JSX 66 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md 67 | 'react/jsx-boolean-value': ['error', 'never', { always: [] }], 68 | 69 | // Validate closing bracket location in JSX 70 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md 71 | 'react/jsx-closing-bracket-location': ['error', 'line-aligned'], 72 | 73 | // Validate closing tag location in JSX 74 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md 75 | 'react/jsx-closing-tag-location': 'error', 76 | 77 | // Enforce or disallow spaces inside of curly braces in JSX attributes 78 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md 79 | 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }], 80 | 81 | // Enforce event handler naming conventions in JSX 82 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md 83 | 'react/jsx-handler-names': ['off', { 84 | eventHandlerPrefix: 'handle', 85 | eventHandlerPropPrefix: 'on', 86 | }], 87 | 88 | // Validate props indentation in JSX 89 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md 90 | 'react/jsx-indent-props': ['error', 2], 91 | 92 | // Validate JSX has key prop when in array or iterator 93 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md 94 | 'react/jsx-key': 'off', 95 | 96 | // Limit maximum of props on a single line in JSX 97 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md 98 | 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }], 99 | 100 | // Prevent usage of .bind() in JSX props 101 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 102 | 'react/jsx-no-bind': ['error', { 103 | ignoreRefs: true, 104 | allowArrowFunctions: true, 105 | allowFunctions: false, 106 | allowBind: false, 107 | ignoreDOMComponents: true, 108 | }], 109 | 110 | // Prevent duplicate props in JSX 111 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md 112 | 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }], 113 | 114 | // Prevent usage of unwrapped JSX strings 115 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md 116 | 'react/jsx-no-literals': ['off', { noStrings: true }], 117 | 118 | // Disallow undeclared variables in JSX 119 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md 120 | 'react/jsx-no-undef': 'error', 121 | 122 | // Enforce PascalCase for user-defined JSX components 123 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md 124 | 'react/jsx-pascal-case': ['error', { 125 | allowAllCaps: true, 126 | ignore: [], 127 | }], 128 | 129 | // Enforce propTypes declarations alphabetical sorting 130 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md 131 | 'react/sort-prop-types': ['off', { 132 | ignoreCase: true, 133 | callbacksLast: false, 134 | requiredFirst: false, 135 | sortShapeProp: true, 136 | }], 137 | 138 | // Deprecated in favor of react/jsx-sort-props 139 | 'react/jsx-sort-prop-types': 'off', 140 | 141 | // Enforce props alphabetical sorting 142 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md 143 | 'react/jsx-sort-props': ['off', { 144 | ignoreCase: true, 145 | callbacksLast: false, 146 | shorthandFirst: false, 147 | shorthandLast: false, 148 | noSortAlphabetically: false, 149 | reservedFirst: true, 150 | }], 151 | 152 | // Enforce defaultProps declarations alphabetical sorting 153 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-sort-default-props.md 154 | 'react/jsx-sort-default-props': ['off', { 155 | ignoreCase: true, 156 | }], 157 | 158 | // Prevent React to be incorrectly marked as unused 159 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md 160 | 'react/jsx-uses-react': ['error'], 161 | 162 | // Prevent variables used in JSX to be incorrectly marked as unused 163 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md 164 | 'react/jsx-uses-vars': 'error', 165 | 166 | // Prevent usage of dangerous JSX properties 167 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md 168 | 'react/no-danger': 'warn', 169 | 170 | // Prevent usage of deprecated methods 171 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md 172 | 'react/no-deprecated': ['error'], 173 | 174 | // Prevent usage of setState in componentDidMount 175 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md 176 | // this is necessary for server-rendering 177 | 'react/no-did-mount-set-state': 'off', 178 | 179 | // Prevent usage of setState in componentDidUpdate 180 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md 181 | 'react/no-did-update-set-state': 'error', 182 | 183 | // Prevent usage of setState in componentWillUpdate 184 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md 185 | 'react/no-will-update-set-state': 'error', 186 | 187 | // Prevent direct mutation of this.state 188 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md 189 | 'react/no-direct-mutation-state': 'off', 190 | 191 | // Prevent usage of isMounted 192 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md 193 | 'react/no-is-mounted': 'error', 194 | 195 | // Prevent multiple component definition per file 196 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md 197 | 'react/no-multi-comp': 'off', 198 | 199 | // Prevent usage of setState 200 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md 201 | 'react/no-set-state': 'off', 202 | 203 | // Prevent using string references 204 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md 205 | 'react/no-string-refs': 'error', 206 | 207 | // Prevent usage of unknown DOM property 208 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md 209 | 'react/no-unknown-property': 'error', 210 | 211 | // Require ES6 class declarations over React.createClass 212 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md 213 | 'react/prefer-es6-class': ['error', 'always'], 214 | 215 | // Require stateless functions when not using lifecycle methods, setState or ref 216 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md 217 | 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }], 218 | 219 | // Prevent missing props validation in a React component definition 220 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md 221 | 'react/prop-types': ['error', { 222 | ignore: [], 223 | customValidators: [], 224 | skipUndeclared: false 225 | }], 226 | 227 | // Prevent missing React when using JSX 228 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md 229 | 'react/react-in-jsx-scope': 'error', 230 | 231 | // Require render() methods to return something 232 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md 233 | 'react/require-render-return': 'error', 234 | 235 | // Prevent extra closing tags for components without children 236 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md 237 | 'react/self-closing-comp': 'error', 238 | 239 | // Enforce component methods order 240 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md 241 | 'react/sort-comp': ['error', { 242 | order: [ 243 | 'static-methods', 244 | 'instance-variables', 245 | 'lifecycle', 246 | '/^on.+$/', 247 | 'getters', 248 | 'setters', 249 | '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', 250 | 'instance-methods', 251 | 'everything-else', 252 | 'rendering', 253 | ], 254 | groups: { 255 | lifecycle: [ 256 | 'displayName', 257 | 'propTypes', 258 | 'contextTypes', 259 | 'childContextTypes', 260 | 'mixins', 261 | 'statics', 262 | 'defaultProps', 263 | 'constructor', 264 | 'getDefaultProps', 265 | 'getInitialState', 266 | 'state', 267 | 'getChildContext', 268 | 'componentWillMount', 269 | 'componentDidMount', 270 | 'componentWillReceiveProps', 271 | 'shouldComponentUpdate', 272 | 'componentWillUpdate', 273 | 'componentDidUpdate', 274 | 'componentWillUnmount', 275 | ], 276 | rendering: [ 277 | '/^render.+$/', 278 | 'render' 279 | ], 280 | }, 281 | }], 282 | 283 | // Prevent missing parentheses around multilines JSX 284 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md 285 | 'react/jsx-wrap-multilines': ['error', { 286 | declaration: 'parens-new-line', 287 | assignment: 'parens-new-line', 288 | return: 'parens-new-line', 289 | arrow: 'parens-new-line', 290 | condition: 'parens-new-line', 291 | logical: 'parens-new-line', 292 | prop: 'parens-new-line', 293 | }], 294 | 295 | // Require that the first prop in a JSX element be on a new line when the element is multiline 296 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md 297 | 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], 298 | 299 | // Enforce spacing around jsx equals signs 300 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md 301 | 'react/jsx-equals-spacing': ['error', 'never'], 302 | 303 | // Enforce JSX indentation 304 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md 305 | 'react/jsx-indent': ['error', 2], 306 | 307 | // Disallow target="_blank" on links 308 | // https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-no-target-blank.md 309 | 'react/jsx-no-target-blank': ['error', { enforceDynamicLinks: 'always' }], 310 | 311 | // only .jsx files may have JSX 312 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md 313 | 'react/jsx-filename-extension': ['error', { extensions: ['.jsx'] }], 314 | 315 | // prevent accidental JS comments from being injected into JSX as text 316 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md 317 | 'react/jsx-no-comment-textnodes': 'error', 318 | 319 | // disallow using React.render/ReactDOM.render's return value 320 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md 321 | 'react/no-render-return-value': 'error', 322 | 323 | // require a shouldComponentUpdate method, or PureRenderMixin 324 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-optimization.md 325 | 'react/require-optimization': ['off', { allowDecorators: [] }], 326 | 327 | // warn against using findDOMNode() 328 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md 329 | 'react/no-find-dom-node': 'error', 330 | 331 | // Forbid certain props on Components 332 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md 333 | 'react/forbid-component-props': ['off', { forbid: [] }], 334 | 335 | // Forbid certain elements 336 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md 337 | 'react/forbid-elements': ['off', { forbid: [], }], 338 | 339 | // Prevent problem with children and props.dangerouslySetInnerHTML 340 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md 341 | 'react/no-danger-with-children': 'error', 342 | 343 | // Prevent unused propType definitions 344 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md 345 | 'react/no-unused-prop-types': ['error', { 346 | customValidators: [ 347 | ], 348 | skipShapeProps: true, 349 | }], 350 | 351 | // Require style prop value be an object or var 352 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md 353 | 'react/style-prop-object': 'error', 354 | 355 | // Prevent invalid characters from appearing in markup 356 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md 357 | 'react/no-unescaped-entities': 'error', 358 | 359 | // Prevent passing of children as props 360 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md 361 | 'react/no-children-prop': 'error', 362 | 363 | // Validate whitespace in and around the JSX opening and closing brackets 364 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md 365 | 'react/jsx-tag-spacing': ['error', { 366 | closingSlash: 'never', 367 | beforeSelfClosing: 'always', 368 | afterOpening: 'never', 369 | beforeClosing: 'never', 370 | }], 371 | 372 | // Enforce spaces before the closing bracket of self-closing JSX elements 373 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md 374 | // Deprecated in favor of jsx-tag-spacing 375 | 'react/jsx-space-before-closing': ['off', 'always'], 376 | 377 | // Prevent usage of Array index in keys 378 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md 379 | 'react/no-array-index-key': 'error', 380 | 381 | // Enforce a defaultProps definition for every prop that is not a required prop 382 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/require-default-props.md 383 | 'react/require-default-props': ['error', { 384 | forbidDefaultForRequired: true, 385 | }], 386 | 387 | // Forbids using non-exported propTypes 388 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md 389 | // this is intentionally set to "warn". it would be "error", 390 | // but it's only critical if you're stripping propTypes in production. 391 | 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }], 392 | 393 | // Prevent void DOM elements from receiving children 394 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md 395 | 'react/void-dom-elements-no-children': 'error', 396 | 397 | // Enforce all defaultProps have a corresponding non-required PropType 398 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/default-props-match-prop-types.md 399 | 'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }], 400 | 401 | // Prevent usage of shouldComponentUpdate when extending React.PureComponent 402 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/no-redundant-should-component-update.md 403 | 'react/no-redundant-should-component-update': 'error', 404 | 405 | // Prevent unused state values 406 | // https://github.com/yannickcr/eslint-plugin-react/pull/1103/ 407 | 'react/no-unused-state': 'error', 408 | 409 | // Enforces consistent naming for boolean props 410 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/boolean-prop-naming.md 411 | 'react/boolean-prop-naming': ['off', { 412 | propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], 413 | rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+', 414 | message: '', 415 | }], 416 | 417 | // Prevents common casing typos 418 | // https://github.com/yannickcr/eslint-plugin-react/blob/73abadb697034b5ccb514d79fb4689836fe61f91/docs/rules/no-typos.md 419 | 'react/no-typos': 'error', 420 | 421 | // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children 422 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md 423 | 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], 424 | 425 | // One JSX Element Per Line 426 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md 427 | 'react/jsx-one-expression-per-line': ['error', { allow: 'single-child' }], 428 | 429 | // Enforce consistent usage of destructuring assignment of props, state, and context 430 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/destructuring-assignment.md 431 | 'react/destructuring-assignment': ['error', 'always'], 432 | 433 | // Prevent using this.state within a this.setState 434 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-access-state-in-setstate.md 435 | 'react/no-access-state-in-setstate': 'error', 436 | 437 | // Prevent usage of button elements without an explicit type attribute 438 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md 439 | 'react/button-has-type': ['error', { 440 | button: true, 441 | submit: true, 442 | reset: false, 443 | }], 444 | 445 | // Ensures inline tags are not rendered without spaces between them 446 | 'react/jsx-child-element-spacing': 'off', 447 | 448 | // Prevent this from being used in stateless functional components 449 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md 450 | 'react/no-this-in-sfc': 'error', 451 | 452 | // Validate JSX maximum depth 453 | // https://github.com/yannickcr/eslint-plugin-react/blob/abe8381c0d6748047224c430ce47f02e40160ed0/docs/rules/jsx-max-depth.md 454 | 'react/jsx-max-depth': 'off', 455 | 456 | // Disallow multiple spaces between inline JSX props 457 | // https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-props-no-multi-spaces.md 458 | 'react/jsx-props-no-multi-spaces': 'error', 459 | 460 | // Prevent usage of UNSAFE_ methods 461 | // https://github.com/yannickcr/eslint-plugin-react/blob/157cc932be2cfaa56b3f5b45df6f6d4322a2f660/docs/rules/no-unsafe.md 462 | 'react/no-unsafe': 'off', 463 | 464 | // Enforce shorthand or standard form for React fragments 465 | // https://github.com/yannickcr/eslint-plugin-react/blob/bc976b837abeab1dffd90ac6168b746a83fc83cc/docs/rules/jsx-fragments.md 466 | // TODO: enable, semver-major 467 | 'react/jsx-fragments': ['off', 'syntax'], 468 | }, 469 | 470 | settings: { 471 | 'import/resolver': { 472 | node: { 473 | extensions: ['.js', '.jsx', '.json'] 474 | } 475 | }, 476 | react: { 477 | pragma: 'React', 478 | version: '16.0' 479 | }, 480 | propWrapperFunctions: [ 481 | 'forbidExtraProps', // https://www.npmjs.com/package/airbnb-prop-types 482 | 'exact', // https://www.npmjs.com/package/prop-types-exact 483 | 'Object.freeze', // https://tc39.github.io/ecma262/#sec-object.freeze 484 | ], 485 | } 486 | }; 487 | -------------------------------------------------------------------------------- /react/README.md: -------------------------------------------------------------------------------- 1 | # Airbnb React/JSX Style Guide 2 | 3 | *A mostly reasonable approach to React and JSX* 4 | 5 | This style guide is mostly based on the standards that are currently prevalent in JavaScript, although some conventions (i.e async/await or static class fields) may still be included or prohibited on a case-by-case basis. Currently, anything prior to stage 3 is not included nor recommended in this guide. 6 | 7 | ## Table of Contents 8 | 9 | 1. [Basic Rules](#basic-rules) 10 | 1. [Class vs `React.createClass` vs stateless](#class-vs-reactcreateclass-vs-stateless) 11 | 1. [Mixins](#mixins) 12 | 1. [Naming](#naming) 13 | 1. [Declaration](#declaration) 14 | 1. [Alignment](#alignment) 15 | 1. [Quotes](#quotes) 16 | 1. [Spacing](#spacing) 17 | 1. [Props](#props) 18 | 1. [Refs](#refs) 19 | 1. [Parentheses](#parentheses) 20 | 1. [Tags](#tags) 21 | 1. [Methods](#methods) 22 | 1. [Ordering](#ordering) 23 | 1. [`isMounted`](#ismounted) 24 | 25 | ## Basic Rules 26 | 27 | - Only include one React component per file. 28 | - 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). 29 | - Always use JSX syntax. 30 | - Do not use `React.createElement` unless you’re initializing the app from a file that is not JSX. 31 | - [`react/forbid-prop-types`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md) will allow `arrays` and `objects` only if it is explicitly noted what `array` and `object` contains, using `arrayOf`, `objectOf`, or `shape`. 32 | 33 | ## Class vs `React.createClass` vs stateless 34 | 35 | - If you have internal state and/or refs, prefer `class extends React.Component` over `React.createClass`. eslint: [`react/prefer-es6-class`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md) [`react/prefer-stateless-function`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md) 36 | 37 | ```jsx 38 | // bad 39 | const Listing = React.createClass({ 40 | // ... 41 | render() { 42 | return
{this.state.hello}
; 43 | } 44 | }); 45 | 46 | // good 47 | class Listing extends React.Component { 48 | // ... 49 | render() { 50 | return
{this.state.hello}
; 51 | } 52 | } 53 | ``` 54 | 55 | And if you don’t have state or refs, prefer normal functions (not arrow functions) over classes: 56 | 57 | ```jsx 58 | // bad 59 | class Listing extends React.Component { 60 | render() { 61 | return
{this.props.hello}
; 62 | } 63 | } 64 | 65 | // bad (relying on function name inference is discouraged) 66 | const Listing = ({ hello }) => ( 67 |
{hello}
68 | ); 69 | 70 | // good 71 | function Listing({ hello }) { 72 | return
{hello}
; 73 | } 74 | ``` 75 | 76 | ## Mixins 77 | 78 | - [Do not use mixins](https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html). 79 | 80 | > Why? Mixins introduce implicit dependencies, cause name clashes, and cause snowballing complexity. Most use cases for mixins can be accomplished in better ways via components, higher-order components, or utility modules. 81 | 82 | ## Naming 83 | 84 | - **Extensions**: Use `.jsx` extension for React components. eslint: [`react/jsx-filename-extension`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md) 85 | - **Filename**: Use PascalCase for filenames. E.g., `ReservationCard.jsx`. 86 | - **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) 87 | 88 | ```jsx 89 | // bad 90 | import reservationCard from './ReservationCard'; 91 | 92 | // good 93 | import ReservationCard from './ReservationCard'; 94 | 95 | // bad 96 | const ReservationItem = ; 97 | 98 | // good 99 | const reservationItem = ; 100 | ``` 101 | 102 | - **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: 103 | 104 | ```jsx 105 | // bad 106 | import Footer from './Footer/Footer'; 107 | 108 | // bad 109 | import Footer from './Footer/index'; 110 | 111 | // good 112 | import Footer from './Footer'; 113 | ``` 114 | - **Higher-order Component Naming**: Use a composite of the higher-order component’s name and the passed-in component’s name as the `displayName` on the generated component. For example, the higher-order component `withFoo()`, when passed a component `Bar` should produce a component with a `displayName` of `withFoo(Bar)`. 115 | 116 | > Why? A component’s `displayName` may be used by developer tools or in error messages, and having a value that clearly expresses this relationship helps people understand what is happening. 117 | 118 | ```jsx 119 | // bad 120 | export default function withFoo(WrappedComponent) { 121 | return function WithFoo(props) { 122 | return ; 123 | } 124 | } 125 | 126 | // good 127 | export default function withFoo(WrappedComponent) { 128 | function WithFoo(props) { 129 | return ; 130 | } 131 | 132 | const wrappedComponentName = WrappedComponent.displayName 133 | || WrappedComponent.name 134 | || 'Component'; 135 | 136 | WithFoo.displayName = `withFoo(${wrappedComponentName})`; 137 | return WithFoo; 138 | } 139 | ``` 140 | 141 | - **Props Naming**: Avoid using DOM component prop names for different purposes. 142 | 143 | > Why? People expect props like `style` and `className` to mean one specific thing. Varying this API for a subset of your app makes the code less readable and less maintainable, and may cause bugs. 144 | 145 | ```jsx 146 | // bad 147 | 148 | 149 | // bad 150 | 151 | 152 | // good 153 | 154 | ``` 155 | 156 | ## Declaration 157 | 158 | - Do not use `displayName` for naming components. Instead, name the component by reference. 159 | 160 | ```jsx 161 | // bad 162 | export default React.createClass({ 163 | displayName: 'ReservationCard', 164 | // stuff goes here 165 | }); 166 | 167 | // good 168 | export default class ReservationCard extends React.Component { 169 | } 170 | ``` 171 | 172 | ## Alignment 173 | 174 | - 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) [`react/jsx-closing-tag-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md) 175 | 176 | ```jsx 177 | // bad 178 | 180 | 181 | // good 182 | 186 | 187 | // if props fit in one line then keep it on the same line 188 | 189 | 190 | // children get indented normally 191 | 195 | 196 | 197 | 198 | // bad 199 | {showButton && 200 |