Skip to content

Make errors and warnings nicer #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 120 additions & 187 deletions config/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,22 @@

// 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
// We use eslint-loader so even warnings are very visibile.
// This is why we only use "WARNING" level for potential errors,
// and we don't use "ERROR" level at all.

// In the future, we might create a separate list of rules for production.
// It would probably be more strict.

var WARNING = 1;

module.exports = {
root: true,

parser: 'babel-eslint',

plugins: ['react', 'import'],
// import plugin is termporarily disabled, scroll below to see why
plugins: ['react'/*, 'import'*/],

env: {
es6: true,
Expand Down Expand Up @@ -51,78 +57,40 @@ module.exports = {

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, {
'array-callback-return': WARNING,
'default-case': [WARNING, { commentPattern: '^no default$' }],
'dot-location': [WARNING, 'property'],
eqeqeq: [WARNING, 'allow-null'],
'guard-for-in': WARNING,
'new-cap': [WARNING, { newIsCap: true }],
'new-parens': WARNING,
'no-array-constructor': WARNING,
'no-caller': WARNING,
'no-cond-assign': [WARNING, 'always'],
'no-const-assign': WARNING,
'no-control-regex': WARNING,
'no-delete-var': WARNING,
'no-dupe-args': WARNING,
'no-dupe-class-members': WARNING,
'no-dupe-keys': WARNING,
'no-duplicate-case': WARNING,
'no-empty-character-class': WARNING,
'no-empty-pattern': WARNING,
'no-eval': WARNING,
'no-ex-assign': WARNING,
'no-extend-native': WARNING,
'no-extra-bind': WARNING,
'no-extra-label': WARNING,
'no-fallthrough': WARNING,
'no-func-assign': WARNING,
'no-implied-eval': WARNING,
'no-invalid-regexp': WARNING,
'no-iterator': WARNING,
'no-label-var': WARNING,
'no-labels': [WARNING, { allowLoop: false, allowSwitch: false }],
'no-lone-blocks': WARNING,
'no-loop-func': WARNING,
'no-mixed-operators': [WARNING, {
groups: [
['+', '-', '*', '/', '%', '**'],
['&', '|', '^', '~', '<<', '>>', '>>>'],
Expand All @@ -132,136 +100,101 @@ module.exports = {
],
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': WARNING,
'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-multi-str': WARNING,
'no-native-reassign': WARNING,
'no-negated-in-lhs': WARNING,
'no-new-func': WARNING,
'no-new-object': WARNING,
'no-new-symbol': WARNING,
'no-new-wrappers': WARNING,
'no-obj-calls': WARNING,
'no-octal': WARNING,
'no-octal-escape': WARNING,
'no-redeclare': WARNING,
'no-regex-spaces': WARNING,
'no-restricted-syntax': [
ERROR,
WARNING,
'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: 'none' }],
'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, {
'no-return-assign': WARNING,
'no-script-url': WARNING,
'no-self-assign': WARNING,
'no-self-compare': WARNING,
'no-sequences': WARNING,
'no-shadow-restricted-names': WARNING,
'no-sparse-arrays': WARNING,
'no-this-before-super': WARNING,
'no-throw-literal': WARNING,
'no-undef': WARNING,
'no-unexpected-multiline': WARNING,
'no-unreachable': WARNING,
'no-unused-expressions': WARNING,
'no-unused-labels': WARNING,
'no-unused-vars': [WARNING, { vars: 'local', args: 'none' }],
'no-use-before-define': [WARNING, 'nofunc'],
'no-useless-computed-key': WARNING,
'no-useless-concat': WARNING,
'no-useless-constructor': WARNING,
'no-useless-escape': WARNING,
'no-useless-rename': [WARNING, {
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,
'no-with': WARNING,
'no-whitespace-before-property': WARNING,
'operator-assignment': [WARNING, 'always'],
radix: WARNING,
'require-yield': WARNING,
'rest-spread-spacing': [WARNING, 'never'],
strict: [WARNING, 'never'],
'unicode-bom': [WARNING, 'never'],
'use-isnan': WARNING,
'valid-typeof': 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 }],
// TODO: import rules are temporarily disabled because they don't play well
// with how eslint-loader only checks the file you change. So if module A
// imports module B, and B is missing a default export, the linter will
// record this as an issue in module A. Now if you fix module B, the linter
// will not be aware that it needs to re-lint A as well, so the error
// will stay until the next restart, which is really confusing.

// This is probably fixable with a patch to eslint-loader.
// When file A is saved, we want to invalidate all files that import it
// *and* that currently have lint errors. This should fix the problem.

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

// https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
'react/jsx-equals-spacing': [ERROR, 'never'],
'react/jsx-equals-spacing': [WARNING, '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, {
'react/jsx-no-duplicate-props': [WARNING, { ignoreCase: true }],
'react/jsx-no-undef': WARNING,
'react/jsx-pascal-case': [WARNING, {
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
}]
'react/jsx-uses-react': WARNING,
'react/jsx-uses-vars': WARNING,
'react/no-deprecated': WARNING,
'react/no-direct-mutation-state': WARNING,
'react/no-is-mounted': WARNING,
'react/react-in-jsx-scope': WARNING,
'react/require-render-return': WARNING
}
};
5 changes: 4 additions & 1 deletion config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
entry: [
require.resolve('webpack-dev-server/client') + '?http://localhost:3000',
require.resolve('webpack/hot/dev-server'),
'./src/index.js'
'./src/index'
],
output: {
// Next line is not used in dev but WebpackDevServer crashes without it:
Expand All @@ -30,6 +30,9 @@ module.exports = {
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
extensions: ['', '.js'],
},
resolveLoader: {
root: path.join(__dirname, '..', 'node_modules'),
moduleTemplates: ['*-loader']
Expand Down
5 changes: 4 additions & 1 deletion config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ var relative = isInNodeModules ? '../../..' : '..';
module.exports = {
bail: true,
devtool: 'source-map',
entry: './src/index.js',
entry: './src/index',
output: {
path: path.resolve(__dirname, relative, 'build'),
filename: '[name].[hash].js',
// TODO: this wouldn't work for e.g. GH Pages.
// Good news: we can infer it from package.json :-)
publicPath: '/'
},
resolve: {
extensions: ['', '.js'],
},
resolveLoader: {
root: path.join(__dirname, '..', 'node_modules'),
moduleTemplates: ['*-loader']
Expand Down
Loading