Skip to content

Commit

Permalink
Use a custom ESLint rule list (#27)
Browse files Browse the repository at this point in the history
* Use a custom eslint rule list

* Sort rules

* Relax some rules
  • Loading branch information
gaearon authored Jul 19, 2016
1 parent b8a2b98 commit 3d77f5b
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Currently it is a thin layer on top of many amazing community projects, such as:
* [webpack](https://webpack.github.io/) with [webpack-dev-server](https://github.com/webpack/webpack-dev-server), [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) and [style-loader](https://github.com/webpack/style-loader)
* [Babel](http://babeljs.io/) with [preset-es2015](https://www.npmjs.com/package/babel-preset-es2015), [preset-es2016](https://www.npmjs.com/package/babel-preset-es2016), [preset-react](https://www.npmjs.com/package/babel-preset-react) and [transform-rest-spread](https://babeljs.io/docs/plugins/transform-object-rest-spread/)
* [Autoprefixer](https://github.com/postcss/autoprefixer)
* [ESLint](http://eslint.org/) with [eslint-config-airbnb](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb)
* [ESLint](http://eslint.org/)
* and more.

All of them are transient dependencies of the provided npm package.
Expand Down
3 changes: 0 additions & 3 deletions config/.eslintrc

This file was deleted.

14 changes: 14 additions & 0 deletions config/babel.dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

module.exports = {
cacheDirectory: true,
presets: ['es2015', 'es2016', 'react'],
plugins: ['transform-object-rest-spread']
};
16 changes: 16 additions & 0 deletions config/babel.prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

module.exports = {
presets: ['es2015', 'es2016', 'react'],
plugins: [
'transform-object-rest-spread',
'transform-react-constant-elements'
]
};
265 changes: 265 additions & 0 deletions config/eslint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

// Inspired by https://github.com/airbnb/javascript but less opinionated.

var OFF = 0; // rules that split the community (e.g. semicolons)
var WARNING = 1; // style rules accepted by the majority of popular styleguides
var ERROR = 2; // rules that prevent common mistakes

module.exports = {
root: true,

plugins: ['react', 'import'],

env: {
es6: true,
commonjs: true,
browser: true
},

parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
generators: true,
experimentalObjectRestSpread: true
}
},

settings: {
'import/ignore': [
'node_modules',
'\\.(json|css|jpg|png|gif|eot|svg|ttf|woff|woff2|mp4|webm)$',
],
'import/extensions': ['.js'],
'import/resolver': {
node: {
extensions: ['.js', '.json']
}
}
},

rules: {
// http://eslint.org/docs/rules/
'array-callback-return': ERROR,
'arrow-spacing': [WARNING, { before: true, after: true }],
'block-scoped-var': WARNING,
'block-spacing': [WARNING, 'always'],
'brace-style': [WARNING, '1tbs', { allowSingleLine: true }],
'comma-spacing': [WARNING, { before: false, after: true }],
'comma-style': [WARNING, 'last'],
'computed-property-spacing': [WARNING, 'never'],
curly: [WARNING, 'multi-line'],
'default-case': [ERROR, { commentPattern: '^no default$' }],
'dot-notation': [WARNING, { allowKeywords: true }],
'dot-location': [ERROR, 'property'],
'eol-last': WARNING,
eqeqeq: [ERROR, 'allow-null'],
'generator-star-spacing': [WARNING, { before: false, after: true }],
'guard-for-in': ERROR,
'key-spacing': [WARNING, { beforeColon: false, afterColon: true }],
'keyword-spacing': [WARNING, {
before: true,
after: true,
overrides: {
return: { after: true },
throw: { after: true },
case: { after: true }
}
}],
'linebreak-style': [WARNING, 'unix'],
'new-cap': [ERROR, { newIsCap: true }],
'new-parens': ERROR,
'newline-per-chained-call': [WARNING, { ignoreChainWithDepth: 4 }],
'no-array-constructor': ERROR,
'no-caller': ERROR,
'no-case-declarations': WARNING,
'no-cond-assign': [ERROR, 'always'],
'no-confusing-arrow': [WARNING, {
allowParens: true,
}],
'no-console': OFF, // TODO: enable for production?
'no-constant-condition': WARNING,
'no-const-assign': ERROR,
'no-control-regex': ERROR,
'no-debugger': WARNING, // TODO: enable for production?
'no-delete-var': ERROR,
'no-dupe-args': ERROR,
'no-dupe-class-members': ERROR,
'no-dupe-keys': ERROR,
'no-duplicate-case': ERROR,
'no-duplicate-imports': WARNING,
'no-empty': [WARNING, {
allowEmptyCatch: true
}],
'no-empty-character-class': ERROR,
'no-empty-pattern': ERROR,
'no-eval': ERROR,
'no-ex-assign': ERROR,
'no-extend-native': ERROR,
'no-extra-bind': ERROR,
'no-extra-boolean-cast': WARNING,
'no-extra-label': ERROR,
'no-extra-semi': WARNING,
'no-fallthrough': ERROR,
'no-func-assign': ERROR,
'no-implied-eval': ERROR,
'no-invalid-this': WARNING,
'no-invalid-regexp': ERROR,
'no-irregular-whitespace': WARNING,
'no-iterator': ERROR,
'no-label-var': ERROR,
'no-labels': [ERROR, { allowLoop: false, allowSwitch: false }],
'no-lone-blocks': ERROR,
'no-loop-func': ERROR,
'no-mixed-operators': [ERROR, {
groups: [
['+', '-', '*', '/', '%', '**'],
['&', '|', '^', '~', '<<', '>>', '>>>'],
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
['&&', '||'],
['in', 'instanceof']
],
allowSamePrecedence: false
}],
'no-multi-spaces': WARNING,
'no-multi-str': ERROR,
'no-multiple-empty-lines': [WARNING, { max: 2, maxEOF: 1 }],
'no-native-reassign': ERROR,
'no-negated-in-lhs': ERROR,
'no-nested-ternary': WARNING,
'no-new': ERROR,
'no-new-func': ERROR,
'no-new-object': ERROR,
'no-new-symbol': ERROR,
'no-new-wrappers': ERROR,
'no-obj-calls': ERROR,
'no-octal': ERROR,
'no-octal-escape': ERROR,
'no-prototype-builtins': WARNING,
'no-redeclare': ERROR,
'no-regex-spaces': ERROR,
'no-restricted-syntax': [
ERROR,
'LabeledStatement',
'WithStatement',
],
'no-return-assign': ERROR,
'no-script-url': ERROR,
'no-self-assign': ERROR,
'no-self-compare': ERROR,
'no-sequences': ERROR,
'no-shadow': WARNING,
'no-shadow-restricted-names': ERROR,
'no-spaced-func': WARNING,
'no-sparse-arrays': ERROR,
'no-this-before-super': ERROR,
'no-throw-literal': ERROR,
'no-trailing-spaces': WARNING,
'no-undef': ERROR,
'no-unexpected-multiline': ERROR,
'no-unneeded-ternary': [WARNING, { defaultAssignment: false }],
'no-unreachable': ERROR,
'no-unsafe-finally': WARNING,
'no-unused-expressions': ERROR,
'no-unused-labels': ERROR,
'no-unused-vars': [ERROR, { vars: 'local', args: 'after-used' }],
'no-use-before-define': [ERROR, 'nofunc'],
'no-useless-computed-key': ERROR,
'no-useless-concat': ERROR,
'no-useless-constructor': ERROR,
'no-useless-escape': ERROR,
'no-useless-rename': [ERROR, {
ignoreDestructuring: false,
ignoreImport: false,
ignoreExport: false,
}],
'no-var': WARNING,
'no-with': ERROR,
'no-whitespace-before-property': ERROR,
'object-property-newline': [WARNING, {
allowMultiplePropertiesPerLine: true,
}],
'operator-assignment': [ERROR, 'always'],
radix: ERROR,
'require-yield': ERROR,
'rest-spread-spacing': [ERROR, 'never'],
'semi-spacing': [WARNING, { before: false, after: true }],
'space-before-blocks': WARNING,
'space-before-function-paren': [WARNING, { anonymous: 'always', named: 'never' }],
'space-in-parens': [WARNING, 'never'],
'space-infix-ops': WARNING,
'space-unary-ops': [WARNING, {
words: true,
nonwords: false,
overrides: {},
}],
'spaced-comment': [WARNING, 'always', {
exceptions: ['-', '+'],
markers: ['=', '!']
}],
strict: [ERROR, 'never'],
'template-curly-spacing': WARNING,
'unicode-bom': [ERROR, 'never'],
'use-isnan': ERROR,
'valid-typeof': ERROR,
'yield-star-spacing': [WARNING, 'after'],
yoda: WARNING,

// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/

'import/default': ERROR,
'import/export': ERROR,
'import/imports-first': WARNING,
'import/named': ERROR,
'import/namespace': ERROR,
'import/no-amd': ERROR,
'import/no-commonjs': WARNING,
'import/no-duplicates': ERROR,
'import/no-extraneous-dependencies': ERROR,
'import/no-named-as-default': ERROR,
'import/no-named-as-default-member': ERROR,
'import/no-unresolved': [ERROR, { commonjs: true }],

// https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
'react/jsx-equals-spacing': [ERROR, 'never'],
'react/jsx-handler-names': [WARNING, {
eventHandlerPrefix: 'handle',
eventHandlerPropPrefix: 'on',
}],
'react/jsx-key': WARNING,
'react/jsx-no-duplicate-props': [ERROR, { ignoreCase: true }],
'react/jsx-no-undef': ERROR,
'react/jsx-pascal-case': [ERROR, {
allowAllCaps: true,
ignore: [],
}],
'react/jsx-space-before-closing': WARNING,
'react/jsx-uses-react': [ERROR, { pragma: 'React' }],
'react/jsx-uses-vars': ERROR,
'react/no-deprecated': ERROR,
'react/no-did-mount-set-state': [WARNING, 'allow-in-func'],
'react/no-did-update-set-state': [WARNING, 'allow-in-func'],
'react/no-direct-mutation-state': ERROR,
'react/no-is-mounted': ERROR,
'react/no-multi-comp': [WARNING, { ignoreStateless: true }],
'react/no-string-refs': WARNING,
'react/prefer-es6-class': OFF, // TODO: revisit after updating docs
'react/prefer-stateless-function': OFF, // TODO: revisit after updating docs
'react/react-in-jsx-scope': ERROR,
'react/require-render-return': ERROR,
'react/wrap-multilines': [WARNING, {
declaration: true,
assignment: true,
return: true
}]
}
};
13 changes: 5 additions & 8 deletions config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ var relative = isInNodeModules ? '../../..' : '..';
module.exports = {
devtool: 'eval',
entry: [
'./src/index.js',
'webpack-dev-server/client?http://localhost:3000'
'webpack-dev-server/client?http://localhost:3000',
'./src/index.js'
],
output: {
// Next line is not used in dev but WebpackDevServer crashes without it:
Expand All @@ -42,11 +42,7 @@ module.exports = {
test: /\.js$/,
include: path.resolve(__dirname, relative, 'src'),
loader: 'babel',
query: {
cacheDirectory: true,
presets: ['es2015', 'es2016', 'react'],
plugins: ['transform-object-rest-spread']
}
query: require('./babel.dev')
},
{
test: /\.css$/,
Expand All @@ -68,7 +64,8 @@ module.exports = {
]
},
eslint: {
configFile: path.join(__dirname, '.eslintrc')
configFile: path.join(__dirname, 'eslint.js'),
useEslintrc: false
},
postcss: function() {
return [autoprefixer];
Expand Down
13 changes: 5 additions & 8 deletions config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,7 @@ module.exports = {
test: /\.js$/,
include: path.resolve(__dirname, relative, 'src'),
loader: 'babel',
query: {
presets: ['es2015', 'es2016', 'react'],
plugins: [
'transform-object-rest-spread',
'transform-react-constant-elements'
]
}
query: require('./babel.prod')
},
{
test: /\.css$/,
Expand All @@ -67,7 +61,10 @@ module.exports = {
]
},
eslint: {
configFile: path.join(__dirname, '.eslintrc')
// TODO: consider separate config for production,
// e.g. to enable no-console and no-debugger only in prod.
configFile: path.join(__dirname, 'eslint.js'),
useEslintrc: false
},
postcss: function() {
return [autoprefixer];
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@
"babel-preset-es2015": "^6.9.0",
"babel-preset-es2016": "^6.11.3",
"babel-preset-react": "^6.11.1",
"css-loader": "^0.23.1",
"cross-spawn": "^4.0.0",
"eslint": "^2.13.1",
"eslint-config-airbnb": "^9.0.1",
"css-loader": "^0.23.1",
"eslint": "^3.1.1",
"eslint-loader": "^1.4.1",
"eslint-plugin-import": "^1.10.3",
"eslint-plugin-jsx-a11y": "^1.5.5",
"eslint-plugin-react": "^5.2.2",
"file-loader": "^0.9.0",
"html-webpack-plugin": "^2.22.0",
Expand Down
4 changes: 3 additions & 1 deletion scripts/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ prompt('Are you sure you want to eject? This action is permanent. [y/N]', functi
var hostPath = path.join(selfPath, '..', '..');

var files = [
path.join('config', '.eslintrc'),
path.join('config', 'babel.dev.js'),
path.join('config', 'babel.prod.js'),
path.join('config', 'eslint.js'),
path.join('config', 'webpack.config.dev.js'),
path.join('config', 'webpack.config.prod.js'),
path.join('scripts', 'build.js'),
Expand Down

0 comments on commit 3d77f5b

Please sign in to comment.