Skip to content

Commit 3d77f5b

Browse files
authored
Use a custom ESLint rule list (#27)
* Use a custom eslint rule list * Sort rules * Relax some rules
1 parent b8a2b98 commit 3d77f5b

File tree

9 files changed

+311
-25
lines changed

9 files changed

+311
-25
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Currently it is a thin layer on top of many amazing community projects, such as:
8686
* [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)
8787
* [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/)
8888
* [Autoprefixer](https://github.com/postcss/autoprefixer)
89-
* [ESLint](http://eslint.org/) with [eslint-config-airbnb](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb)
89+
* [ESLint](http://eslint.org/)
9090
* and more.
9191

9292
All of them are transient dependencies of the provided npm package.

config/.eslintrc

Lines changed: 0 additions & 3 deletions
This file was deleted.

config/babel.dev.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
module.exports = {
11+
cacheDirectory: true,
12+
presets: ['es2015', 'es2016', 'react'],
13+
plugins: ['transform-object-rest-spread']
14+
};

config/babel.prod.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
module.exports = {
11+
presets: ['es2015', 'es2016', 'react'],
12+
plugins: [
13+
'transform-object-rest-spread',
14+
'transform-react-constant-elements'
15+
]
16+
};

config/eslint.js

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
// Inspired by https://github.com/airbnb/javascript but less opinionated.
11+
12+
var OFF = 0; // rules that split the community (e.g. semicolons)
13+
var WARNING = 1; // style rules accepted by the majority of popular styleguides
14+
var ERROR = 2; // rules that prevent common mistakes
15+
16+
module.exports = {
17+
root: true,
18+
19+
plugins: ['react', 'import'],
20+
21+
env: {
22+
es6: true,
23+
commonjs: true,
24+
browser: true
25+
},
26+
27+
parserOptions: {
28+
ecmaVersion: 6,
29+
sourceType: 'module',
30+
ecmaFeatures: {
31+
jsx: true,
32+
generators: true,
33+
experimentalObjectRestSpread: true
34+
}
35+
},
36+
37+
settings: {
38+
'import/ignore': [
39+
'node_modules',
40+
'\\.(json|css|jpg|png|gif|eot|svg|ttf|woff|woff2|mp4|webm)$',
41+
],
42+
'import/extensions': ['.js'],
43+
'import/resolver': {
44+
node: {
45+
extensions: ['.js', '.json']
46+
}
47+
}
48+
},
49+
50+
rules: {
51+
// http://eslint.org/docs/rules/
52+
'array-callback-return': ERROR,
53+
'arrow-spacing': [WARNING, { before: true, after: true }],
54+
'block-scoped-var': WARNING,
55+
'block-spacing': [WARNING, 'always'],
56+
'brace-style': [WARNING, '1tbs', { allowSingleLine: true }],
57+
'comma-spacing': [WARNING, { before: false, after: true }],
58+
'comma-style': [WARNING, 'last'],
59+
'computed-property-spacing': [WARNING, 'never'],
60+
curly: [WARNING, 'multi-line'],
61+
'default-case': [ERROR, { commentPattern: '^no default$' }],
62+
'dot-notation': [WARNING, { allowKeywords: true }],
63+
'dot-location': [ERROR, 'property'],
64+
'eol-last': WARNING,
65+
eqeqeq: [ERROR, 'allow-null'],
66+
'generator-star-spacing': [WARNING, { before: false, after: true }],
67+
'guard-for-in': ERROR,
68+
'key-spacing': [WARNING, { beforeColon: false, afterColon: true }],
69+
'keyword-spacing': [WARNING, {
70+
before: true,
71+
after: true,
72+
overrides: {
73+
return: { after: true },
74+
throw: { after: true },
75+
case: { after: true }
76+
}
77+
}],
78+
'linebreak-style': [WARNING, 'unix'],
79+
'new-cap': [ERROR, { newIsCap: true }],
80+
'new-parens': ERROR,
81+
'newline-per-chained-call': [WARNING, { ignoreChainWithDepth: 4 }],
82+
'no-array-constructor': ERROR,
83+
'no-caller': ERROR,
84+
'no-case-declarations': WARNING,
85+
'no-cond-assign': [ERROR, 'always'],
86+
'no-confusing-arrow': [WARNING, {
87+
allowParens: true,
88+
}],
89+
'no-console': OFF, // TODO: enable for production?
90+
'no-constant-condition': WARNING,
91+
'no-const-assign': ERROR,
92+
'no-control-regex': ERROR,
93+
'no-debugger': WARNING, // TODO: enable for production?
94+
'no-delete-var': ERROR,
95+
'no-dupe-args': ERROR,
96+
'no-dupe-class-members': ERROR,
97+
'no-dupe-keys': ERROR,
98+
'no-duplicate-case': ERROR,
99+
'no-duplicate-imports': WARNING,
100+
'no-empty': [WARNING, {
101+
allowEmptyCatch: true
102+
}],
103+
'no-empty-character-class': ERROR,
104+
'no-empty-pattern': ERROR,
105+
'no-eval': ERROR,
106+
'no-ex-assign': ERROR,
107+
'no-extend-native': ERROR,
108+
'no-extra-bind': ERROR,
109+
'no-extra-boolean-cast': WARNING,
110+
'no-extra-label': ERROR,
111+
'no-extra-semi': WARNING,
112+
'no-fallthrough': ERROR,
113+
'no-func-assign': ERROR,
114+
'no-implied-eval': ERROR,
115+
'no-invalid-this': WARNING,
116+
'no-invalid-regexp': ERROR,
117+
'no-irregular-whitespace': WARNING,
118+
'no-iterator': ERROR,
119+
'no-label-var': ERROR,
120+
'no-labels': [ERROR, { allowLoop: false, allowSwitch: false }],
121+
'no-lone-blocks': ERROR,
122+
'no-loop-func': ERROR,
123+
'no-mixed-operators': [ERROR, {
124+
groups: [
125+
['+', '-', '*', '/', '%', '**'],
126+
['&', '|', '^', '~', '<<', '>>', '>>>'],
127+
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
128+
['&&', '||'],
129+
['in', 'instanceof']
130+
],
131+
allowSamePrecedence: false
132+
}],
133+
'no-multi-spaces': WARNING,
134+
'no-multi-str': ERROR,
135+
'no-multiple-empty-lines': [WARNING, { max: 2, maxEOF: 1 }],
136+
'no-native-reassign': ERROR,
137+
'no-negated-in-lhs': ERROR,
138+
'no-nested-ternary': WARNING,
139+
'no-new': ERROR,
140+
'no-new-func': ERROR,
141+
'no-new-object': ERROR,
142+
'no-new-symbol': ERROR,
143+
'no-new-wrappers': ERROR,
144+
'no-obj-calls': ERROR,
145+
'no-octal': ERROR,
146+
'no-octal-escape': ERROR,
147+
'no-prototype-builtins': WARNING,
148+
'no-redeclare': ERROR,
149+
'no-regex-spaces': ERROR,
150+
'no-restricted-syntax': [
151+
ERROR,
152+
'LabeledStatement',
153+
'WithStatement',
154+
],
155+
'no-return-assign': ERROR,
156+
'no-script-url': ERROR,
157+
'no-self-assign': ERROR,
158+
'no-self-compare': ERROR,
159+
'no-sequences': ERROR,
160+
'no-shadow': WARNING,
161+
'no-shadow-restricted-names': ERROR,
162+
'no-spaced-func': WARNING,
163+
'no-sparse-arrays': ERROR,
164+
'no-this-before-super': ERROR,
165+
'no-throw-literal': ERROR,
166+
'no-trailing-spaces': WARNING,
167+
'no-undef': ERROR,
168+
'no-unexpected-multiline': ERROR,
169+
'no-unneeded-ternary': [WARNING, { defaultAssignment: false }],
170+
'no-unreachable': ERROR,
171+
'no-unsafe-finally': WARNING,
172+
'no-unused-expressions': ERROR,
173+
'no-unused-labels': ERROR,
174+
'no-unused-vars': [ERROR, { vars: 'local', args: 'after-used' }],
175+
'no-use-before-define': [ERROR, 'nofunc'],
176+
'no-useless-computed-key': ERROR,
177+
'no-useless-concat': ERROR,
178+
'no-useless-constructor': ERROR,
179+
'no-useless-escape': ERROR,
180+
'no-useless-rename': [ERROR, {
181+
ignoreDestructuring: false,
182+
ignoreImport: false,
183+
ignoreExport: false,
184+
}],
185+
'no-var': WARNING,
186+
'no-with': ERROR,
187+
'no-whitespace-before-property': ERROR,
188+
'object-property-newline': [WARNING, {
189+
allowMultiplePropertiesPerLine: true,
190+
}],
191+
'operator-assignment': [ERROR, 'always'],
192+
radix: ERROR,
193+
'require-yield': ERROR,
194+
'rest-spread-spacing': [ERROR, 'never'],
195+
'semi-spacing': [WARNING, { before: false, after: true }],
196+
'space-before-blocks': WARNING,
197+
'space-before-function-paren': [WARNING, { anonymous: 'always', named: 'never' }],
198+
'space-in-parens': [WARNING, 'never'],
199+
'space-infix-ops': WARNING,
200+
'space-unary-ops': [WARNING, {
201+
words: true,
202+
nonwords: false,
203+
overrides: {},
204+
}],
205+
'spaced-comment': [WARNING, 'always', {
206+
exceptions: ['-', '+'],
207+
markers: ['=', '!']
208+
}],
209+
strict: [ERROR, 'never'],
210+
'template-curly-spacing': WARNING,
211+
'unicode-bom': [ERROR, 'never'],
212+
'use-isnan': ERROR,
213+
'valid-typeof': ERROR,
214+
'yield-star-spacing': [WARNING, 'after'],
215+
yoda: WARNING,
216+
217+
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/
218+
219+
'import/default': ERROR,
220+
'import/export': ERROR,
221+
'import/imports-first': WARNING,
222+
'import/named': ERROR,
223+
'import/namespace': ERROR,
224+
'import/no-amd': ERROR,
225+
'import/no-commonjs': WARNING,
226+
'import/no-duplicates': ERROR,
227+
'import/no-extraneous-dependencies': ERROR,
228+
'import/no-named-as-default': ERROR,
229+
'import/no-named-as-default-member': ERROR,
230+
'import/no-unresolved': [ERROR, { commonjs: true }],
231+
232+
// https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
233+
'react/jsx-equals-spacing': [ERROR, 'never'],
234+
'react/jsx-handler-names': [WARNING, {
235+
eventHandlerPrefix: 'handle',
236+
eventHandlerPropPrefix: 'on',
237+
}],
238+
'react/jsx-key': WARNING,
239+
'react/jsx-no-duplicate-props': [ERROR, { ignoreCase: true }],
240+
'react/jsx-no-undef': ERROR,
241+
'react/jsx-pascal-case': [ERROR, {
242+
allowAllCaps: true,
243+
ignore: [],
244+
}],
245+
'react/jsx-space-before-closing': WARNING,
246+
'react/jsx-uses-react': [ERROR, { pragma: 'React' }],
247+
'react/jsx-uses-vars': ERROR,
248+
'react/no-deprecated': ERROR,
249+
'react/no-did-mount-set-state': [WARNING, 'allow-in-func'],
250+
'react/no-did-update-set-state': [WARNING, 'allow-in-func'],
251+
'react/no-direct-mutation-state': ERROR,
252+
'react/no-is-mounted': ERROR,
253+
'react/no-multi-comp': [WARNING, { ignoreStateless: true }],
254+
'react/no-string-refs': WARNING,
255+
'react/prefer-es6-class': OFF, // TODO: revisit after updating docs
256+
'react/prefer-stateless-function': OFF, // TODO: revisit after updating docs
257+
'react/react-in-jsx-scope': ERROR,
258+
'react/require-render-return': ERROR,
259+
'react/wrap-multilines': [WARNING, {
260+
declaration: true,
261+
assignment: true,
262+
return: true
263+
}]
264+
}
265+
};

config/webpack.config.dev.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ var relative = isInNodeModules ? '../../..' : '..';
1919
module.exports = {
2020
devtool: 'eval',
2121
entry: [
22-
'./src/index.js',
23-
'webpack-dev-server/client?http://localhost:3000'
22+
'webpack-dev-server/client?http://localhost:3000',
23+
'./src/index.js'
2424
],
2525
output: {
2626
// Next line is not used in dev but WebpackDevServer crashes without it:
@@ -42,11 +42,7 @@ module.exports = {
4242
test: /\.js$/,
4343
include: path.resolve(__dirname, relative, 'src'),
4444
loader: 'babel',
45-
query: {
46-
cacheDirectory: true,
47-
presets: ['es2015', 'es2016', 'react'],
48-
plugins: ['transform-object-rest-spread']
49-
}
45+
query: require('./babel.dev')
5046
},
5147
{
5248
test: /\.css$/,
@@ -68,7 +64,8 @@ module.exports = {
6864
]
6965
},
7066
eslint: {
71-
configFile: path.join(__dirname, '.eslintrc')
67+
configFile: path.join(__dirname, 'eslint.js'),
68+
useEslintrc: false
7269
},
7370
postcss: function() {
7471
return [autoprefixer];

config/webpack.config.prod.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,7 @@ module.exports = {
3939
test: /\.js$/,
4040
include: path.resolve(__dirname, relative, 'src'),
4141
loader: 'babel',
42-
query: {
43-
presets: ['es2015', 'es2016', 'react'],
44-
plugins: [
45-
'transform-object-rest-spread',
46-
'transform-react-constant-elements'
47-
]
48-
}
42+
query: require('./babel.prod')
4943
},
5044
{
5145
test: /\.css$/,
@@ -67,7 +61,10 @@ module.exports = {
6761
]
6862
},
6963
eslint: {
70-
configFile: path.join(__dirname, '.eslintrc')
64+
// TODO: consider separate config for production,
65+
// e.g. to enable no-console and no-debugger only in prod.
66+
configFile: path.join(__dirname, 'eslint.js'),
67+
useEslintrc: false
7168
},
7269
postcss: function() {
7370
return [autoprefixer];

package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@
2929
"babel-preset-es2015": "^6.9.0",
3030
"babel-preset-es2016": "^6.11.3",
3131
"babel-preset-react": "^6.11.1",
32-
"css-loader": "^0.23.1",
3332
"cross-spawn": "^4.0.0",
34-
"eslint": "^2.13.1",
35-
"eslint-config-airbnb": "^9.0.1",
33+
"css-loader": "^0.23.1",
34+
"eslint": "^3.1.1",
3635
"eslint-loader": "^1.4.1",
3736
"eslint-plugin-import": "^1.10.3",
38-
"eslint-plugin-jsx-a11y": "^1.5.5",
3937
"eslint-plugin-react": "^5.2.2",
4038
"file-loader": "^0.9.0",
4139
"html-webpack-plugin": "^2.22.0",

scripts/eject.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ prompt('Are you sure you want to eject? This action is permanent. [y/N]', functi
4040
var hostPath = path.join(selfPath, '..', '..');
4141

4242
var files = [
43-
path.join('config', '.eslintrc'),
43+
path.join('config', 'babel.dev.js'),
44+
path.join('config', 'babel.prod.js'),
45+
path.join('config', 'eslint.js'),
4446
path.join('config', 'webpack.config.dev.js'),
4547
path.join('config', 'webpack.config.prod.js'),
4648
path.join('scripts', 'build.js'),

0 commit comments

Comments
 (0)