From faa6d71c09a7da45d24ed815f98226e3717461c0 Mon Sep 17 00:00:00 2001 From: Vitaly Kramskikh Date: Sun, 17 Jan 2016 17:51:58 +0300 Subject: [PATCH] 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 --- .eslintrc | 55 +-------------------------- gulp/i18n.js | 3 +- gulpfile.js | 20 +++++----- karma.config.js | 94 ++++++++++++++++++++++----------------------- static/.eslintrc | 57 ++++++++++++++++++++++++++++ webpack.config.js | 97 ++++++++++++++++++++++++----------------------- 6 files changed, 165 insertions(+), 161 deletions(-) create mode 100644 static/.eslintrc diff --git a/.eslintrc b/.eslintrc index 7acec227a..b19de248f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,21 +1,6 @@ --- root: true 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: # disabled rules from openstack config no-empty: 0 # we use empty blocks with try-catch @@ -59,43 +44,5 @@ quotes: [2, single, avoid-escape] space-before-function-paren: [2, never] 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: - browser: true - globals: - app: false + node: true diff --git a/gulp/i18n.js b/gulp/i18n.js index 58a9be770..25a6c608e 100644 --- a/gulp/i18n.js +++ b/gulp/i18n.js @@ -1,6 +1,7 @@ +/*eslint-disable strict*/ + 'use strict'; -var fs = require('fs'); var gutil = require('gulp-util'); var _ = require('lodash'); diff --git a/gulpfile.js b/gulpfile.js index 218d38bb3..407d0cc67 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -14,7 +14,7 @@ * under the License. **/ -/*eslint-env node*/ +/*eslint-disable strict*/ 'use strict'; @@ -92,7 +92,7 @@ gulp.task('selenium', ['selenium:fetch'], function(cb) { gulp.task('karma', function(cb) { var Server = require('karma').Server; new Server({ - configFile: __dirname + '/karma.config.js', + configFile: path.join(__dirname, '/karma.config.js'), browsers: [argv.browser || process.env.BROWSER || 'firefox'] }, cb).start(); }); @@ -148,7 +148,7 @@ gulp.task('jison', function() { gulp.task('license', function(cb) { 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 // Is the library license compatible? // Preferably Apache2, BSD, MIT licensed. LGPL is ok. @@ -171,25 +171,25 @@ gulp.task('license', function(cb) { _.each(errors, function(error) { gutil.log(gutil.colors.red(error.libraryName, 'has', error.license, 'license')); }); - cb('Issues with licenses found'); + return cb('Issues with licenses found'); } else { - cb(); + return cb(); } }); }); var jsFiles = [ + '*.js', + 'gulp/*.js', 'static/**/*.js', '!static/build/**', '!static/vendor/**', - '!static/expression/parser.js', - 'static/tests/**/*.js' + '!static/expression/parser.js' ]; var styleFiles = [ 'static/**/*.less', 'static/**/*.css', - '!static/build/**', - '!static/vendor/**' + '!static/build/**' ]; gulp.task('eslint', function() { @@ -323,7 +323,7 @@ gulp.task('build', function(cb) { .pipe(gulp.dest(targetDir)) .on('end', cb); } else if (!config.watch) { - cb(); + return cb(); } }); }); diff --git a/karma.config.js b/karma.config.js index 0a809b19d..f42067be2 100644 --- a/karma.config.js +++ b/karma.config.js @@ -1,52 +1,50 @@ /*eslint-disable strict*/ -var webpackConfig = require('./webpack.config'); - module.exports = function(config) { - config.set({ - browsers: ['firefox'], - files: [ - 'static/tests/unit/**/*.js' - ], - frameworks: [ - 'chai', - 'mocha', - 'sinon' - ], - plugins: [ - 'karma-webdriver-launcher', - 'karma-chai', - 'karma-mocha', - 'karma-sinon', - 'karma-webpack' - ], - preprocessors: { - 'static/tests/unit/**/*.js': ['webpack'] - }, - reporters: ['dots'], - singleRun: true, - client: { - mocha: { - ui: 'tdd' - } - }, - customLaunchers: { - chrome: { - base: 'WebDriver', - browserName: 'chrome' - }, - firefox: { - base: 'WebDriver', - browserName: 'firefox' - }, - phantomjs: { - base: 'WebDriver', - browserName: 'phantomjs' - } - }, - webpack: webpackConfig, - webpackMiddleware: { - noInfo: true - } - }); + config.set({ + browsers: ['firefox'], + files: [ + 'static/tests/unit/**/*.js' + ], + frameworks: [ + 'chai', + 'mocha', + 'sinon' + ], + plugins: [ + 'karma-webdriver-launcher', + 'karma-chai', + 'karma-mocha', + 'karma-sinon', + 'karma-webpack' + ], + preprocessors: { + 'static/tests/unit/**/*.js': ['webpack'] + }, + reporters: ['dots'], + singleRun: true, + client: { + mocha: { + ui: 'tdd' + } + }, + customLaunchers: { + chrome: { + base: 'WebDriver', + browserName: 'chrome' + }, + firefox: { + base: 'WebDriver', + browserName: 'firefox' + }, + phantomjs: { + base: 'WebDriver', + browserName: 'phantomjs' + } + }, + webpack: require('./webpack.config'), + webpackMiddleware: { + noInfo: true + } + }); }; diff --git a/static/.eslintrc b/static/.eslintrc new file mode 100644 index 000000000..a76955fcd --- /dev/null +++ b/static/.eslintrc @@ -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 diff --git a/webpack.config.js b/webpack.config.js index 48529fefb..3f57876e5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,52 +1,53 @@ /*eslint-disable strict*/ + module.exports = { - entry: [ - 'babel-core/polyfill', - './static/app.js' - ], - output: { - path: __dirname + '/static/build/', - publicPath: '/static/build/', - filename: 'bundle.js', - chunkFilename: null, - sourceMapFilename: 'bundle.js.map' - }, - module: { - loaders: [ - { - test: /\.js$/, - loader: 'babel', - exclude: [/(node_modules|vendor\/custom)\//, /\/expression\/parser\.js$/], - query: {cacheDirectory: true} - }, - {test: /\/expression\/parser\.js$/, loader: 'exports?parser'}, - {test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$'}, - {test: /\/sinon\.js$/, loader: 'imports?this=>window,define=>false,exports=>false,module=>false,require=>false'}, - {test: /\.css$/, loader: 'style!css!postcss'}, - {test: /\.less$/, loader: 'style!css!postcss!less'}, - {test: /\.html$/, loader: 'raw'}, - {test: /\.json$/, loader: 'json'}, - {test: /\.jison$/, loader: 'jison'}, - {test: /\.(gif|png)$/, loader: 'file'}, - {test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'} - ] - }, - resolve: { - modulesDirectories: ['static', 'node_modules', 'vendor/custom'], - extensions: ['', '.js'], - alias: { - underscore: 'lodash', - sinon: 'sinon/pkg/sinon.js' - } - }, - node: {}, - plugins: [], - postcss: function() { - return [require('autoprefixer')]; - }, - devtool: 'cheap-module-source-map', - watchOptions: { - aggregateTimeout: 300, - poll: 1000 + entry: [ + 'babel-core/polyfill', + './static/app.js' + ], + output: { + path: require('path').join(__dirname, '/static/build/'), + publicPath: '/static/build/', + filename: 'bundle.js', + chunkFilename: null, + sourceMapFilename: 'bundle.js.map' + }, + module: { + loaders: [ + { + test: /\.js$/, + loader: 'babel', + exclude: [/(node_modules|vendor\/custom)\//, /\/expression\/parser\.js$/], + query: {cacheDirectory: true} + }, + {test: /\/expression\/parser\.js$/, loader: 'exports?parser'}, + {test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$'}, + {test: /\/sinon\.js$/, loader: 'imports?this=>window,define=>false,exports=>false,module=>false,require=>false'}, + {test: /\.css$/, loader: 'style!css!postcss'}, + {test: /\.less$/, loader: 'style!css!postcss!less'}, + {test: /\.html$/, loader: 'raw'}, + {test: /\.json$/, loader: 'json'}, + {test: /\.jison$/, loader: 'jison'}, + {test: /\.(gif|png)$/, loader: 'file'}, + {test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'} + ] + }, + resolve: { + modulesDirectories: ['static', 'node_modules', 'vendor/custom'], + extensions: ['', '.js'], + alias: { + underscore: 'lodash', + sinon: 'sinon/pkg/sinon.js' } + }, + node: {}, + plugins: [], + postcss: function() { + return [require('autoprefixer')]; + }, + devtool: 'cheap-module-source-map', + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } };