Enable linting for node.js files and split .eslintrc

This commit enables linting for node.js files (gulpfile and
helpers, webpack and karma configs) and also splits .eslintrc
into 2 files. This is needed because our node.js files don't
support ES6 syntax, so nailgun/.eslintrc now contains common
linting rules and nailgun/static/.eslintrc contains JSX
and ES6-specific rules.

Implements: blueprint converge-to-eslint-config-openstack

Change-Id: I1956f2022475b39724dfb49f98bdc8e6e5d898e9
This commit is contained in:
Vitaly Kramskikh 2016-01-17 17:51:58 +03:00
parent 631ad02db8
commit faa6d71c09
6 changed files with 165 additions and 161 deletions

View File

@ -1,21 +1,6 @@
--- ---
root: true root: true
extends: openstack extends: openstack
plugins:
- react
ecmaFeatures:
arrowFunctions: true
classes: true
defaultParams: true
destructuring: true
jsx: true
modules: true
objectLiteralComputedProperties: true
objectLiteralShorthandMethods: true
objectLiteralShorthandProperties: true
restParams: true
spread: true
superInFunctions: true
rules: rules:
# disabled rules from openstack config # disabled rules from openstack config
no-empty: 0 # we use empty blocks with try-catch no-empty: 0 # we use empty blocks with try-catch
@ -59,43 +44,5 @@
quotes: [2, single, avoid-escape] quotes: [2, single, avoid-escape]
space-before-function-paren: [2, never] space-before-function-paren: [2, never]
space-before-keywords: 2 space-before-keywords: 2
# es6
arrow-parens: 2
arrow-spacing: 2
constructor-super: 2
no-class-assign: 2
no-const-assign: 2
no-dupe-class-members: 2
no-this-before-super: 2
no-var: 0
object-shorthand: [2, methods]
prefer-arrow-callback: 2
prefer-const: 0
prefer-spread: 2
prefer-template: 0
# react
react/jsx-boolean-value: [2, never]
react/jsx-closing-bracket-location: [2, {nonEmpty: false, selfClosing: line-aligned}]
react/jsx-curly-spacing: [2, never]
react/jsx-indent: [2, 2]
react/jsx-indent-props: [2, 2]
react/jsx-key: 2
react/jsx-no-duplicate-props: 2
react/jsx-no-literals: 0
react/jsx-no-undef: 2
react/jsx-pascal-case: 2
react/jsx-uses-react: 2
react/jsx-uses-vars: 2
react/no-deprecated: 2
react/no-unknown-property: 2
react/prefer-es6-class: [2, never]
react/prop-types: 0
react/react-in-jsx-scope: 2
react/self-closing-comp: 2
react/sort-comp: 0
env: env:
browser: true node: true
globals:
app: false

View File

@ -1,6 +1,7 @@
/*eslint-disable strict*/
'use strict'; 'use strict';
var fs = require('fs');
var gutil = require('gulp-util'); var gutil = require('gulp-util');
var _ = require('lodash'); var _ = require('lodash');

View File

@ -14,7 +14,7 @@
* under the License. * under the License.
**/ **/
/*eslint-env node*/ /*eslint-disable strict*/
'use strict'; 'use strict';
@ -92,7 +92,7 @@ gulp.task('selenium', ['selenium:fetch'], function(cb) {
gulp.task('karma', function(cb) { gulp.task('karma', function(cb) {
var Server = require('karma').Server; var Server = require('karma').Server;
new Server({ new Server({
configFile: __dirname + '/karma.config.js', configFile: path.join(__dirname, '/karma.config.js'),
browsers: [argv.browser || process.env.BROWSER || 'firefox'] browsers: [argv.browser || process.env.BROWSER || 'firefox']
}, cb).start(); }, cb).start();
}); });
@ -148,7 +148,7 @@ gulp.task('jison', function() {
gulp.task('license', function(cb) { gulp.task('license', function(cb) {
require('nlf').find({production: true, depth: 0}, function(err, data) { require('nlf').find({production: true, depth: 0}, function(err, data) {
if (err) cb(err); if (err) return cb(err);
// https://github.com/openstack/requirements#for-new-requirements // https://github.com/openstack/requirements#for-new-requirements
// Is the library license compatible? // Is the library license compatible?
// Preferably Apache2, BSD, MIT licensed. LGPL is ok. // Preferably Apache2, BSD, MIT licensed. LGPL is ok.
@ -171,25 +171,25 @@ gulp.task('license', function(cb) {
_.each(errors, function(error) { _.each(errors, function(error) {
gutil.log(gutil.colors.red(error.libraryName, 'has', error.license, 'license')); gutil.log(gutil.colors.red(error.libraryName, 'has', error.license, 'license'));
}); });
cb('Issues with licenses found'); return cb('Issues with licenses found');
} else { } else {
cb(); return cb();
} }
}); });
}); });
var jsFiles = [ var jsFiles = [
'*.js',
'gulp/*.js',
'static/**/*.js', 'static/**/*.js',
'!static/build/**', '!static/build/**',
'!static/vendor/**', '!static/vendor/**',
'!static/expression/parser.js', '!static/expression/parser.js'
'static/tests/**/*.js'
]; ];
var styleFiles = [ var styleFiles = [
'static/**/*.less', 'static/**/*.less',
'static/**/*.css', 'static/**/*.css',
'!static/build/**', '!static/build/**'
'!static/vendor/**'
]; ];
gulp.task('eslint', function() { gulp.task('eslint', function() {
@ -323,7 +323,7 @@ gulp.task('build', function(cb) {
.pipe(gulp.dest(targetDir)) .pipe(gulp.dest(targetDir))
.on('end', cb); .on('end', cb);
} else if (!config.watch) { } else if (!config.watch) {
cb(); return cb();
} }
}); });
}); });

View File

@ -1,52 +1,50 @@
/*eslint-disable strict*/ /*eslint-disable strict*/
var webpackConfig = require('./webpack.config');
module.exports = function(config) { module.exports = function(config) {
config.set({ config.set({
browsers: ['firefox'], browsers: ['firefox'],
files: [ files: [
'static/tests/unit/**/*.js' 'static/tests/unit/**/*.js'
], ],
frameworks: [ frameworks: [
'chai', 'chai',
'mocha', 'mocha',
'sinon' 'sinon'
], ],
plugins: [ plugins: [
'karma-webdriver-launcher', 'karma-webdriver-launcher',
'karma-chai', 'karma-chai',
'karma-mocha', 'karma-mocha',
'karma-sinon', 'karma-sinon',
'karma-webpack' 'karma-webpack'
], ],
preprocessors: { preprocessors: {
'static/tests/unit/**/*.js': ['webpack'] 'static/tests/unit/**/*.js': ['webpack']
}, },
reporters: ['dots'], reporters: ['dots'],
singleRun: true, singleRun: true,
client: { client: {
mocha: { mocha: {
ui: 'tdd' ui: 'tdd'
} }
}, },
customLaunchers: { customLaunchers: {
chrome: { chrome: {
base: 'WebDriver', base: 'WebDriver',
browserName: 'chrome' browserName: 'chrome'
}, },
firefox: { firefox: {
base: 'WebDriver', base: 'WebDriver',
browserName: 'firefox' browserName: 'firefox'
}, },
phantomjs: { phantomjs: {
base: 'WebDriver', base: 'WebDriver',
browserName: 'phantomjs' browserName: 'phantomjs'
} }
}, },
webpack: webpackConfig, webpack: require('./webpack.config'),
webpackMiddleware: { webpackMiddleware: {
noInfo: true noInfo: true
} }
}); });
}; };

57
static/.eslintrc Normal file
View File

@ -0,0 +1,57 @@
---
plugins:
- react
ecmaFeatures:
arrowFunctions: true
classes: true
defaultParams: true
destructuring: true
jsx: true
modules: true
objectLiteralComputedProperties: true
objectLiteralShorthandMethods: true
objectLiteralShorthandProperties: true
restParams: true
spread: true
superInFunctions: true
rules:
# es6
arrow-parens: 2
arrow-spacing: 2
constructor-super: 2
no-class-assign: 2
no-const-assign: 2
no-dupe-class-members: 2
no-this-before-super: 2
no-var: 0
object-shorthand: [2, methods]
prefer-arrow-callback: 2
prefer-const: 0
prefer-spread: 2
prefer-template: 0
# react
react/jsx-boolean-value: [2, never]
react/jsx-closing-bracket-location: [2, {nonEmpty: false, selfClosing: line-aligned}]
react/jsx-curly-spacing: [2, never]
react/jsx-indent: [2, 2]
react/jsx-indent-props: [2, 2]
react/jsx-key: 2
react/jsx-no-duplicate-props: 2
react/jsx-no-literals: 0
react/jsx-no-undef: 2
react/jsx-pascal-case: 2
react/jsx-uses-react: 2
react/jsx-uses-vars: 2
react/no-deprecated: 2
react/no-unknown-property: 2
react/prefer-es6-class: [2, never]
react/prop-types: 0
react/react-in-jsx-scope: 2
react/self-closing-comp: 2
react/sort-comp: 0
env:
browser: true
node: false
globals:
app: false

View File

@ -1,52 +1,53 @@
/*eslint-disable strict*/ /*eslint-disable strict*/
module.exports = { module.exports = {
entry: [ entry: [
'babel-core/polyfill', 'babel-core/polyfill',
'./static/app.js' './static/app.js'
], ],
output: { output: {
path: __dirname + '/static/build/', path: require('path').join(__dirname, '/static/build/'),
publicPath: '/static/build/', publicPath: '/static/build/',
filename: 'bundle.js', filename: 'bundle.js',
chunkFilename: null, chunkFilename: null,
sourceMapFilename: 'bundle.js.map' sourceMapFilename: 'bundle.js.map'
}, },
module: { module: {
loaders: [ loaders: [
{ {
test: /\.js$/, test: /\.js$/,
loader: 'babel', loader: 'babel',
exclude: [/(node_modules|vendor\/custom)\//, /\/expression\/parser\.js$/], exclude: [/(node_modules|vendor\/custom)\//, /\/expression\/parser\.js$/],
query: {cacheDirectory: true} query: {cacheDirectory: true}
}, },
{test: /\/expression\/parser\.js$/, loader: 'exports?parser'}, {test: /\/expression\/parser\.js$/, loader: 'exports?parser'},
{test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$'}, {test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$'},
{test: /\/sinon\.js$/, loader: 'imports?this=>window,define=>false,exports=>false,module=>false,require=>false'}, {test: /\/sinon\.js$/, loader: 'imports?this=>window,define=>false,exports=>false,module=>false,require=>false'},
{test: /\.css$/, loader: 'style!css!postcss'}, {test: /\.css$/, loader: 'style!css!postcss'},
{test: /\.less$/, loader: 'style!css!postcss!less'}, {test: /\.less$/, loader: 'style!css!postcss!less'},
{test: /\.html$/, loader: 'raw'}, {test: /\.html$/, loader: 'raw'},
{test: /\.json$/, loader: 'json'}, {test: /\.json$/, loader: 'json'},
{test: /\.jison$/, loader: 'jison'}, {test: /\.jison$/, loader: 'jison'},
{test: /\.(gif|png)$/, loader: 'file'}, {test: /\.(gif|png)$/, loader: 'file'},
{test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'} {test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'}
] ]
}, },
resolve: { resolve: {
modulesDirectories: ['static', 'node_modules', 'vendor/custom'], modulesDirectories: ['static', 'node_modules', 'vendor/custom'],
extensions: ['', '.js'], extensions: ['', '.js'],
alias: { alias: {
underscore: 'lodash', underscore: 'lodash',
sinon: 'sinon/pkg/sinon.js' sinon: 'sinon/pkg/sinon.js'
}
},
node: {},
plugins: [],
postcss: function() {
return [require('autoprefixer')];
},
devtool: 'cheap-module-source-map',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
} }
},
node: {},
plugins: [],
postcss: function() {
return [require('autoprefixer')];
},
devtool: 'cheap-module-source-map',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
}; };