Skip to content

Commit 9df1c2f

Browse files
authored
Make errors and warnings nicer (#50)
* Make errors and warnings nicer * Fix license stripping to not be eager * Minor tweaks
1 parent 9652973 commit 9df1c2f

File tree

6 files changed

+221
-211
lines changed

6 files changed

+221
-211
lines changed

config/eslint.js

Lines changed: 120 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@
99

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

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
12+
// We use eslint-loader so even warnings are very visibile.
13+
// This is why we only use "WARNING" level for potential errors,
14+
// and we don't use "ERROR" level at all.
15+
16+
// In the future, we might create a separate list of rules for production.
17+
// It would probably be more strict.
18+
19+
var WARNING = 1;
1520

1621
module.exports = {
1722
root: true,
1823

1924
parser: 'babel-eslint',
2025

21-
plugins: ['react', 'import'],
26+
// import plugin is termporarily disabled, scroll below to see why
27+
plugins: ['react'/*, 'import'*/],
2228

2329
env: {
2430
es6: true,
@@ -51,78 +57,40 @@ module.exports = {
5157

5258
rules: {
5359
// http://eslint.org/docs/rules/
54-
'array-callback-return': ERROR,
55-
'arrow-spacing': [WARNING, { before: true, after: true }],
56-
'block-scoped-var': WARNING,
57-
'block-spacing': [WARNING, 'always'],
58-
'brace-style': [WARNING, '1tbs', { allowSingleLine: true }],
59-
'comma-spacing': [WARNING, { before: false, after: true }],
60-
'comma-style': [WARNING, 'last'],
61-
'computed-property-spacing': [WARNING, 'never'],
62-
curly: [WARNING, 'multi-line'],
63-
'default-case': [ERROR, { commentPattern: '^no default$' }],
64-
'dot-notation': [WARNING, { allowKeywords: true }],
65-
'dot-location': [ERROR, 'property'],
66-
'eol-last': WARNING,
67-
eqeqeq: [ERROR, 'allow-null'],
68-
'generator-star-spacing': [WARNING, { before: false, after: true }],
69-
'guard-for-in': ERROR,
70-
'key-spacing': [WARNING, { beforeColon: false, afterColon: true }],
71-
'keyword-spacing': [WARNING, {
72-
before: true,
73-
after: true,
74-
overrides: {
75-
return: { after: true },
76-
throw: { after: true },
77-
case: { after: true }
78-
}
79-
}],
80-
'linebreak-style': [WARNING, 'unix'],
81-
'new-cap': [ERROR, { newIsCap: true }],
82-
'new-parens': ERROR,
83-
'newline-per-chained-call': [WARNING, { ignoreChainWithDepth: 4 }],
84-
'no-array-constructor': ERROR,
85-
'no-caller': ERROR,
86-
'no-case-declarations': WARNING,
87-
'no-cond-assign': [ERROR, 'always'],
88-
'no-confusing-arrow': [WARNING, {
89-
allowParens: true,
90-
}],
91-
'no-console': OFF, // TODO: enable for production?
92-
'no-constant-condition': WARNING,
93-
'no-const-assign': ERROR,
94-
'no-control-regex': ERROR,
95-
'no-debugger': WARNING, // TODO: enable for production?
96-
'no-delete-var': ERROR,
97-
'no-dupe-args': ERROR,
98-
'no-dupe-class-members': ERROR,
99-
'no-dupe-keys': ERROR,
100-
'no-duplicate-case': ERROR,
101-
'no-duplicate-imports': WARNING,
102-
'no-empty': [WARNING, {
103-
allowEmptyCatch: true
104-
}],
105-
'no-empty-character-class': ERROR,
106-
'no-empty-pattern': ERROR,
107-
'no-eval': ERROR,
108-
'no-ex-assign': ERROR,
109-
'no-extend-native': ERROR,
110-
'no-extra-bind': ERROR,
111-
'no-extra-boolean-cast': WARNING,
112-
'no-extra-label': ERROR,
113-
'no-extra-semi': WARNING,
114-
'no-fallthrough': ERROR,
115-
'no-func-assign': ERROR,
116-
'no-implied-eval': ERROR,
117-
'no-invalid-this': WARNING,
118-
'no-invalid-regexp': ERROR,
119-
'no-irregular-whitespace': WARNING,
120-
'no-iterator': ERROR,
121-
'no-label-var': ERROR,
122-
'no-labels': [ERROR, { allowLoop: false, allowSwitch: false }],
123-
'no-lone-blocks': ERROR,
124-
'no-loop-func': ERROR,
125-
'no-mixed-operators': [ERROR, {
60+
'array-callback-return': WARNING,
61+
'default-case': [WARNING, { commentPattern: '^no default$' }],
62+
'dot-location': [WARNING, 'property'],
63+
eqeqeq: [WARNING, 'allow-null'],
64+
'guard-for-in': WARNING,
65+
'new-cap': [WARNING, { newIsCap: true }],
66+
'new-parens': WARNING,
67+
'no-array-constructor': WARNING,
68+
'no-caller': WARNING,
69+
'no-cond-assign': [WARNING, 'always'],
70+
'no-const-assign': WARNING,
71+
'no-control-regex': WARNING,
72+
'no-delete-var': WARNING,
73+
'no-dupe-args': WARNING,
74+
'no-dupe-class-members': WARNING,
75+
'no-dupe-keys': WARNING,
76+
'no-duplicate-case': WARNING,
77+
'no-empty-character-class': WARNING,
78+
'no-empty-pattern': WARNING,
79+
'no-eval': WARNING,
80+
'no-ex-assign': WARNING,
81+
'no-extend-native': WARNING,
82+
'no-extra-bind': WARNING,
83+
'no-extra-label': WARNING,
84+
'no-fallthrough': WARNING,
85+
'no-func-assign': WARNING,
86+
'no-implied-eval': WARNING,
87+
'no-invalid-regexp': WARNING,
88+
'no-iterator': WARNING,
89+
'no-label-var': WARNING,
90+
'no-labels': [WARNING, { allowLoop: false, allowSwitch: false }],
91+
'no-lone-blocks': WARNING,
92+
'no-loop-func': WARNING,
93+
'no-mixed-operators': [WARNING, {
12694
groups: [
12795
['+', '-', '*', '/', '%', '**'],
12896
['&', '|', '^', '~', '<<', '>>', '>>>'],
@@ -132,136 +100,101 @@ module.exports = {
132100
],
133101
allowSamePrecedence: false
134102
}],
135-
'no-multi-spaces': WARNING,
136-
'no-multi-str': ERROR,
137-
'no-multiple-empty-lines': [WARNING, { max: 2, maxEOF: 1 }],
138-
'no-native-reassign': ERROR,
139-
'no-negated-in-lhs': ERROR,
140-
'no-nested-ternary': WARNING,
141-
'no-new': WARNING,
142-
'no-new-func': ERROR,
143-
'no-new-object': ERROR,
144-
'no-new-symbol': ERROR,
145-
'no-new-wrappers': ERROR,
146-
'no-obj-calls': ERROR,
147-
'no-octal': ERROR,
148-
'no-octal-escape': ERROR,
149-
'no-prototype-builtins': WARNING,
150-
'no-redeclare': ERROR,
151-
'no-regex-spaces': ERROR,
103+
'no-multi-str': WARNING,
104+
'no-native-reassign': WARNING,
105+
'no-negated-in-lhs': WARNING,
106+
'no-new-func': WARNING,
107+
'no-new-object': WARNING,
108+
'no-new-symbol': WARNING,
109+
'no-new-wrappers': WARNING,
110+
'no-obj-calls': WARNING,
111+
'no-octal': WARNING,
112+
'no-octal-escape': WARNING,
113+
'no-redeclare': WARNING,
114+
'no-regex-spaces': WARNING,
152115
'no-restricted-syntax': [
153-
ERROR,
116+
WARNING,
154117
'LabeledStatement',
155118
'WithStatement',
156119
],
157-
'no-return-assign': ERROR,
158-
'no-script-url': ERROR,
159-
'no-self-assign': ERROR,
160-
'no-self-compare': ERROR,
161-
'no-sequences': ERROR,
162-
'no-shadow': WARNING,
163-
'no-shadow-restricted-names': ERROR,
164-
'no-spaced-func': WARNING,
165-
'no-sparse-arrays': ERROR,
166-
'no-this-before-super': ERROR,
167-
'no-throw-literal': ERROR,
168-
'no-trailing-spaces': WARNING,
169-
'no-undef': ERROR,
170-
'no-unexpected-multiline': ERROR,
171-
'no-unneeded-ternary': [WARNING, { defaultAssignment: false }],
172-
'no-unreachable': ERROR,
173-
'no-unsafe-finally': WARNING,
174-
'no-unused-expressions': ERROR,
175-
'no-unused-labels': ERROR,
176-
'no-unused-vars': [ERROR, { vars: 'local', args: 'none' }],
177-
'no-use-before-define': [ERROR, 'nofunc'],
178-
'no-useless-computed-key': ERROR,
179-
'no-useless-concat': ERROR,
180-
'no-useless-constructor': ERROR,
181-
'no-useless-escape': ERROR,
182-
'no-useless-rename': [ERROR, {
120+
'no-return-assign': WARNING,
121+
'no-script-url': WARNING,
122+
'no-self-assign': WARNING,
123+
'no-self-compare': WARNING,
124+
'no-sequences': WARNING,
125+
'no-shadow-restricted-names': WARNING,
126+
'no-sparse-arrays': WARNING,
127+
'no-this-before-super': WARNING,
128+
'no-throw-literal': WARNING,
129+
'no-undef': WARNING,
130+
'no-unexpected-multiline': WARNING,
131+
'no-unreachable': WARNING,
132+
'no-unused-expressions': WARNING,
133+
'no-unused-labels': WARNING,
134+
'no-unused-vars': [WARNING, { vars: 'local', args: 'none' }],
135+
'no-use-before-define': [WARNING, 'nofunc'],
136+
'no-useless-computed-key': WARNING,
137+
'no-useless-concat': WARNING,
138+
'no-useless-constructor': WARNING,
139+
'no-useless-escape': WARNING,
140+
'no-useless-rename': [WARNING, {
183141
ignoreDestructuring: false,
184142
ignoreImport: false,
185143
ignoreExport: false,
186144
}],
187-
'no-var': WARNING,
188-
'no-with': ERROR,
189-
'no-whitespace-before-property': ERROR,
190-
'object-property-newline': [WARNING, {
191-
allowMultiplePropertiesPerLine: true,
192-
}],
193-
'operator-assignment': [ERROR, 'always'],
194-
radix: ERROR,
195-
'require-yield': ERROR,
196-
'rest-spread-spacing': [ERROR, 'never'],
197-
'semi-spacing': [WARNING, { before: false, after: true }],
198-
'space-before-blocks': WARNING,
199-
'space-before-function-paren': [WARNING, { anonymous: 'always', named: 'never' }],
200-
'space-in-parens': [WARNING, 'never'],
201-
'space-infix-ops': WARNING,
202-
'space-unary-ops': [WARNING, {
203-
words: true,
204-
nonwords: false,
205-
overrides: {},
206-
}],
207-
'spaced-comment': [WARNING, 'always', {
208-
exceptions: ['-', '+'],
209-
markers: ['=', '!']
210-
}],
211-
strict: [ERROR, 'never'],
212-
'template-curly-spacing': WARNING,
213-
'unicode-bom': [ERROR, 'never'],
214-
'use-isnan': ERROR,
215-
'valid-typeof': ERROR,
216-
'yield-star-spacing': [WARNING, 'after'],
217-
yoda: WARNING,
145+
'no-with': WARNING,
146+
'no-whitespace-before-property': WARNING,
147+
'operator-assignment': [WARNING, 'always'],
148+
radix: WARNING,
149+
'require-yield': WARNING,
150+
'rest-spread-spacing': [WARNING, 'never'],
151+
strict: [WARNING, 'never'],
152+
'unicode-bom': [WARNING, 'never'],
153+
'use-isnan': WARNING,
154+
'valid-typeof': WARNING,
218155

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

221-
'import/default': ERROR,
222-
'import/export': ERROR,
223-
'import/imports-first': WARNING,
224-
'import/named': ERROR,
225-
'import/namespace': ERROR,
226-
'import/no-amd': ERROR,
227-
'import/no-commonjs': WARNING,
228-
'import/no-duplicates': ERROR,
229-
'import/no-extraneous-dependencies': ERROR,
230-
'import/no-named-as-default': ERROR,
231-
'import/no-named-as-default-member': ERROR,
232-
'import/no-unresolved': [ERROR, { commonjs: true }],
158+
// TODO: import rules are temporarily disabled because they don't play well
159+
// with how eslint-loader only checks the file you change. So if module A
160+
// imports module B, and B is missing a default export, the linter will
161+
// record this as an issue in module A. Now if you fix module B, the linter
162+
// will not be aware that it needs to re-lint A as well, so the error
163+
// will stay until the next restart, which is really confusing.
164+
165+
// This is probably fixable with a patch to eslint-loader.
166+
// When file A is saved, we want to invalidate all files that import it
167+
// *and* that currently have lint errors. This should fix the problem.
168+
169+
// 'import/default': WARNING,
170+
// 'import/export': WARNING,
171+
// 'import/named': WARNING,
172+
// 'import/namespace': WARNING,
173+
// 'import/no-amd': WARNING,
174+
// 'import/no-duplicates': WARNING,
175+
// 'import/no-extraneous-dependencies': WARNING,
176+
// 'import/no-named-as-default': WARNING,
177+
// 'import/no-named-as-default-member': WARNING,
178+
// 'import/no-unresolved': [WARNING, { commonjs: true }],
233179

234180
// https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
235-
'react/jsx-equals-spacing': [ERROR, 'never'],
181+
'react/jsx-equals-spacing': [WARNING, 'never'],
236182
'react/jsx-handler-names': [WARNING, {
237183
eventHandlerPrefix: 'handle',
238184
eventHandlerPropPrefix: 'on',
239185
}],
240-
'react/jsx-key': WARNING,
241-
'react/jsx-no-duplicate-props': [ERROR, { ignoreCase: true }],
242-
'react/jsx-no-undef': ERROR,
243-
'react/jsx-pascal-case': [ERROR, {
186+
'react/jsx-no-duplicate-props': [WARNING, { ignoreCase: true }],
187+
'react/jsx-no-undef': WARNING,
188+
'react/jsx-pascal-case': [WARNING, {
244189
allowAllCaps: true,
245190
ignore: [],
246191
}],
247-
'react/jsx-space-before-closing': WARNING,
248-
'react/jsx-uses-react': [ERROR, { pragma: 'React' }],
249-
'react/jsx-uses-vars': ERROR,
250-
'react/no-deprecated': ERROR,
251-
'react/no-did-mount-set-state': [WARNING, 'allow-in-func'],
252-
'react/no-did-update-set-state': [WARNING, 'allow-in-func'],
253-
'react/no-direct-mutation-state': ERROR,
254-
'react/no-is-mounted': ERROR,
255-
'react/no-multi-comp': [WARNING, { ignoreStateless: true }],
256-
'react/no-string-refs': WARNING,
257-
'react/prefer-es6-class': OFF, // TODO: revisit after updating docs
258-
'react/prefer-stateless-function': OFF, // TODO: revisit after updating docs
259-
'react/react-in-jsx-scope': ERROR,
260-
'react/require-render-return': ERROR,
261-
'react/wrap-multilines': [WARNING, {
262-
declaration: true,
263-
assignment: true,
264-
return: true
265-
}]
192+
'react/jsx-uses-react': WARNING,
193+
'react/jsx-uses-vars': WARNING,
194+
'react/no-deprecated': WARNING,
195+
'react/no-direct-mutation-state': WARNING,
196+
'react/no-is-mounted': WARNING,
197+
'react/react-in-jsx-scope': WARNING,
198+
'react/require-render-return': WARNING
266199
}
267200
};

config/webpack.config.dev.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module.exports = {
2121
entry: [
2222
require.resolve('webpack-dev-server/client') + '?http://localhost:3000',
2323
require.resolve('webpack/hot/dev-server'),
24-
'./src/index.js'
24+
'./src/index'
2525
],
2626
output: {
2727
// Next line is not used in dev but WebpackDevServer crashes without it:
@@ -30,6 +30,9 @@ module.exports = {
3030
filename: 'bundle.js',
3131
publicPath: '/'
3232
},
33+
resolve: {
34+
extensions: ['', '.js'],
35+
},
3336
resolveLoader: {
3437
root: path.join(__dirname, '..', 'node_modules'),
3538
moduleTemplates: ['*-loader']

config/webpack.config.prod.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var relative = isInNodeModules ? '../../..' : '..';
2020
module.exports = {
2121
bail: true,
2222
devtool: 'source-map',
23-
entry: './src/index.js',
23+
entry: './src/index',
2424
output: {
2525
path: path.resolve(__dirname, relative, 'build'),
2626
filename: '[name].[chunkhash].js',
@@ -29,6 +29,9 @@ module.exports = {
2929
// Good news: we can infer it from package.json :-)
3030
publicPath: '/'
3131
},
32+
resolve: {
33+
extensions: ['', '.js'],
34+
},
3235
resolveLoader: {
3336
root: path.join(__dirname, '..', 'node_modules'),
3437
moduleTemplates: ['*-loader']

0 commit comments

Comments
 (0)