From 0a43ad1c8a95904195196fb10c003af7ec94c3b1 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 9 Mar 2017 15:09:37 +0700 Subject: [PATCH] ES2015ify --- .editorconfig | 3 - .eslintrc | 121 ----------------------- .gitattributes | 1 + .travis.yml | 5 +- benchmark/env.js | 8 +- gulpfile.js | 56 ++++------- lib/adapter.js | 25 +++-- lib/environment.js | 126 ++++++++++-------------- lib/resolver.js | 80 +++++++-------- lib/store.js | 19 ++-- lib/util/log.js | 68 ++++++------- lib/util/util.js | 10 +- package.json | 12 ++- readme.md | 17 ++-- test/adapter.js | 58 ++++++----- test/environment.js | 20 ++-- test/fixtures/generator-simple/index.js | 2 +- test/resolver.js | 78 +++++++-------- test/store.js | 16 +-- test/util.js | 20 ++-- 20 files changed, 286 insertions(+), 459 deletions(-) delete mode 100644 .eslintrc diff --git a/.editorconfig b/.editorconfig index 6f382402..c16bbae9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,8 +7,5 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.md] -trim_trailing_whitespace = false - [Makefile] indent_style = tab diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index edb52720..00000000 --- a/.eslintrc +++ /dev/null @@ -1,121 +0,0 @@ -{ - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 6 - }, - "env": { - "node": true, - "mocha": true - }, - "rules": { - "array-bracket-spacing": [ - 2, - "never" - ], - "brace-style": [ - 2, - "1tbs" - ], - "consistent-return": 0, - "indent": [ - 2, - 2, - { - "SwitchCase": 1 - } - ], - "no-multiple-empty-lines": [ - 2, - { - "max": 2 - } - ], - "no-use-before-define": [ - 2, - "nofunc" - ], - "one-var": [ - 2, - "never" - ], - "quote-props": [ - 2, - "as-needed" - ], - "quotes": [ - 2, - "single" - ], - "strict": [ - 2, - "global" - ], - "curly": [ - 2, - "all" - ], - "eol-last": 2, - "keyword-spacing": 2, - "key-spacing": [ - 2, - { - "beforeColon": false, - "afterColon": true - } - ], - "no-eval": 2, - "no-with": 2, - "space-infix-ops": 2, - "dot-notation": [ - 2, - { - "allowKeywords": true - } - ], - "eqeqeq": [ - 2, - "allow-null" - ], - "no-alert": 2, - "no-caller": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-implied-eval": 2, - "no-iterator": 2, - "no-label-var": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-multi-spaces": 2, - "no-multi-str": 2, - "no-native-reassign": 2, - "no-new-func": 2, - "no-new-wrappers": 2, - "no-octal-escape": 2, - "no-proto": 2, - "no-return-assign": 2, - "no-script-url": 2, - "no-sequences": 2, - "no-unused-expressions": 2, - "yoda": 2, - "no-undef-init": 2, - "camelcase": 2, - "comma-spacing": 2, - "new-cap": 2, - "new-parens": 2, - "no-array-constructor": 2, - "no-extra-parens": 2, - "no-console": 0, - "no-new-object": 2, - "no-spaced-func": 2, - "no-trailing-spaces": 2, - "semi": 2, - "semi-spacing": [ - 2, - { - "before": false, - "after": true - } - ] - } -} diff --git a/.gitattributes b/.gitattributes index 176a458f..391f0a4e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ * text=auto +*.js text eol=lf diff --git a/.travis.yml b/.travis.yml index df4a65dd..0d14662e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ sudo: false language: node_js node_js: - - v6 - - v5 - - v4 + - '6' + - '4' before_script: - export NODE_PATH="$NVM_PATH/../node_modules" env: diff --git a/benchmark/env.js b/benchmark/env.js index ee85e842..5b658e8a 100644 --- a/benchmark/env.js +++ b/benchmark/env.js @@ -1,9 +1,9 @@ -/*global suite, bench */ +/* global suite, bench */ 'use strict'; -var yeoman = require('..'); +const yeoman = require('..'); -suite('Environment', function () { - bench('#lookup()', function (done) { +suite('Environment', () => { + bench('#lookup()', done => { yeoman.createEnv().lookup(done); }); }); diff --git a/gulpfile.js b/gulpfile.js index 55114e5a..71bcf085 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,50 +1,34 @@ 'use strict'; -var path = require('path'); -var gulp = require('gulp'); -var eslint = require('gulp-eslint'); -var excludeGitignore = require('gulp-exclude-gitignore'); -var mocha = require('gulp-mocha'); -var istanbul = require('gulp-istanbul'); -var nsp = require('gulp-nsp'); -var plumber = require('gulp-plumber'); -var coveralls = require('gulp-coveralls'); - -gulp.task('static', function () { - return gulp.src('**/*.js') - .pipe(excludeGitignore()) - .pipe(eslint()) - .pipe(eslint.format()) - .pipe(eslint.failAfterError()); -}); - -gulp.task('nsp', function (cb) { +const path = require('path'); +const gulp = require('gulp'); +const mocha = require('gulp-mocha'); +const istanbul = require('gulp-istanbul'); +const nsp = require('gulp-nsp'); +const plumber = require('gulp-plumber'); +const coveralls = require('gulp-coveralls'); + +gulp.task('nsp', cb => { nsp({package: path.resolve('package.json')}, cb); }); -gulp.task('pre-test', function () { - return gulp.src('lib/**/*.js') +gulp.task('pre-test', () => + gulp.src('lib/**/*.js') .pipe(istanbul({ includeUntested: true })) - .pipe(istanbul.hookRequire()); -}); - -gulp.task('test', ['pre-test'], function (cb) { - var mochaErr; + .pipe(istanbul.hookRequire()) +); +gulp.task('test', ['pre-test'], () => gulp.src('test/*.js') .pipe(plumber()) - .pipe(mocha({reporter: 'spec'})) - .on('error', function (err) { - mochaErr = err; - }) + .pipe(mocha({ + reporter: 'spec' + })) .pipe(istanbul.writeReports()) - .on('end', function () { - cb(mochaErr); - }); -}); +); -gulp.task('coveralls', ['test'], function () { +gulp.task('coveralls', ['test'], () => { if (!process.env.CI) { return; } @@ -54,4 +38,4 @@ gulp.task('coveralls', ['test'], function () { }); gulp.task('prepublish', ['nsp']); -gulp.task('default', ['static', 'test', 'coveralls']); +gulp.task('default', ['test', 'coveralls']); diff --git a/lib/adapter.js b/lib/adapter.js index 4331da31..a252cf32 100644 --- a/lib/adapter.js +++ b/lib/adapter.js @@ -1,10 +1,9 @@ 'use strict'; - -var _ = require('lodash'); -var inquirer = require('inquirer'); -var diff = require('diff'); -var chalk = require('chalk'); -var logger = require('./util/log'); +const _ = require('lodash'); +const inquirer = require('inquirer'); +const diff = require('diff'); +const chalk = require('chalk'); +const logger = require('./util/log'); /** * `TerminalAdapter` is the default implementation of `Adapter`, an abstraction @@ -14,16 +13,14 @@ var logger = require('./util/log'); * * @constructor */ -var TerminalAdapter = module.exports = function TerminalAdapter() { +const TerminalAdapter = module.exports = function TerminalAdapter() { this.promptModule = inquirer.createPromptModule(); }; TerminalAdapter.prototype._colorDiffAdded = chalk.black.bgGreen; TerminalAdapter.prototype._colorDiffRemoved = chalk.bgRed; TerminalAdapter.prototype._colorLines = function colorLines(name, str) { - return str.split('\n').map(function (line) { - return this['_colorDiff' + name](line); - }, this).join('\n'); + return str.split('\n').map(line => this[`_colorDiff${name}`](line)).join('\n'); }; /** @@ -47,7 +44,7 @@ TerminalAdapter.prototype.prompt = function () {}; * @param {string} expected */ TerminalAdapter.prototype.diff = function _diff(actual, expected) { - var msg = diff.diffLines(actual, expected).map(function (str) { + let msg = diff.diffLines(actual, expected).map(str => { if (str.added) { return this._colorLines('Added', str.value); } @@ -57,9 +54,9 @@ TerminalAdapter.prototype.diff = function _diff(actual, expected) { } return str.value; - }, this).join(''); + }).join(''); - // legend + // Legend msg = '\n' + this._colorDiffRemoved('removed') + ' ' + @@ -79,7 +76,7 @@ TerminalAdapter.prototype.diff = function _diff(actual, expected) { TerminalAdapter.prototype.log = logger(); TerminalAdapter.prototype.prompt = function (questions, cb) { - var promise = this.promptModule(questions); + const promise = this.promptModule(questions); promise.then(cb || _.noop); return promise; }; diff --git a/lib/environment.js b/lib/environment.js index 81fea92b..4e731f80 100644 --- a/lib/environment.js +++ b/lib/environment.js @@ -1,18 +1,18 @@ 'use strict'; -var util = require('util'); -var fs = require('fs'); -var path = require('path'); -var events = require('events'); -var chalk = require('chalk'); -var _ = require('lodash'); -var GroupedQueue = require('grouped-queue'); -var escapeStrRe = require('escape-string-regexp'); -var untildify = require('untildify'); -var memFs = require('mem-fs'); -var debug = require('debug')('yeoman:environment'); -var Store = require('./store'); -var resolver = require('./resolver'); -var TerminalAdapter = require('./adapter'); +const util = require('util'); +const fs = require('fs'); +const path = require('path'); +const events = require('events'); +const chalk = require('chalk'); +const _ = require('lodash'); +const GroupedQueue = require('grouped-queue'); +const escapeStrRe = require('escape-string-regexp'); +const untildify = require('untildify'); +const memFs = require('mem-fs'); +const debug = require('debug')('yeoman:environment'); +const Store = require('./store'); +const resolver = require('./resolver'); +const TerminalAdapter = require('./adapter'); /** * `Environment` object is responsible of handling the lifecyle and bootstrap @@ -36,8 +36,7 @@ var TerminalAdapter = require('./adapter'); * implementing this adapter interface. This is how * you'd interface Yeoman with a GUI or an editor. */ - -var Environment = module.exports = function Environment(args, opts, adapter) { +const Environment = module.exports = function Environment(args, opts, adapter) { events.EventEmitter.call(this); args = args || []; @@ -84,7 +83,6 @@ Environment.queues = [ * @param {Object} err * @return {Error} err */ - Environment.prototype.error = function error(err) { err = err instanceof Error ? err : new Error(err); @@ -101,11 +99,10 @@ Environment.prototype.error = function error(err) { * * @param {String} name */ - Environment.prototype.help = function help(name) { name = name || 'init'; - var out = [ + const out = [ 'Usage: :binary: GENERATOR [args] [options]', '', 'General options:', @@ -116,11 +113,11 @@ Environment.prototype.help = function help(name) { '' ]; - var ns = this.namespaces(); + const ns = this.namespaces(); - var groups = {}; - ns.forEach(function (namespace) { - var base = namespace.split(':')[0]; + const groups = {}; + ns.forEach(namespace => { + const base = namespace.split(':')[0]; if (!groups[base]) { groups[base] = []; @@ -129,15 +126,15 @@ Environment.prototype.help = function help(name) { groups[base].push(namespace); }); - Object.keys(groups).sort().forEach(function (key) { - var group = groups[key]; + Object.keys(groups).sort().forEach(key => { + const group = groups[key]; if (group.length >= 1) { out.push('', key.charAt(0).toUpperCase() + key.slice(1)); } - groups[key].forEach(function (ns) { - out.push(' ' + ns); + groups[key].forEach(ns => { + out.push(` ${ns}`); }); }); @@ -152,13 +149,12 @@ Environment.prototype.help = function help(name) { * @param {String} namespace - Namespace under which register the generator (optional) * @return {String} namespace - Namespace assigned to the registered generator */ - Environment.prototype.register = function register(name, namespace) { if (!_.isString(name)) { return this.error(new Error('You must provide a generator name to register.')); } - var modulePath = this.resolveModulePath(name); + const modulePath = this.resolveModulePath(name); namespace = namespace || this.namespace(modulePath); if (!namespace) { @@ -180,7 +176,6 @@ Environment.prototype.register = function register(name, namespace) { * @param {String} namespace - Namespace under which register the generator * @return {this} */ - Environment.prototype.registerStub = function registerStub(Generator, namespace) { if (!_.isFunction(Generator)) { return this.error(new Error('You must provide a stub function to register.')); @@ -199,7 +194,6 @@ Environment.prototype.registerStub = function registerStub(Generator, namespace) * Returns the list of registered namespace. * @return {Array} */ - Environment.prototype.namespaces = function namespaces() { return this.store.namespaces(); }; @@ -208,7 +202,6 @@ Environment.prototype.namespaces = function namespaces() { * Returns stored generators meta * @return {Object} */ - Environment.prototype.getGeneratorsMeta = function getGeneratorsMeta() { return this.store.getGeneratorsMeta(); }; @@ -218,7 +211,6 @@ Environment.prototype.getGeneratorsMeta = function getGeneratorsMeta() { * * @return {Array} */ - Environment.prototype.getGeneratorNames = function getGeneratorNames() { return _.uniq(Object.keys(this.getGeneratorsMeta()).map(Environment.namespaceToName)); }; @@ -233,20 +225,19 @@ Environment.prototype.getGeneratorNames = function getGeneratorNames() { * @param {String} namespaceOrPath * @return {Generator|null} - the generator registered under the namespace */ - Environment.prototype.get = function get(namespaceOrPath) { // Stop the recursive search if nothing is left if (!namespaceOrPath) { return; } - var namespace = namespaceOrPath; + let namespace = namespaceOrPath; // Legacy yeoman-generator `#hookFor()` function is passing the generator path as part // of the namespace. If we find a path delimiter in the namespace, then ignore the // last part of the namespace. - var parts = namespaceOrPath.split(':'); - var maybePath = _.last(parts); + const parts = namespaceOrPath.split(':'); + const maybePath = _.last(parts); if (parts.length > 1 && /[\/\\]/.test(maybePath)) { parts.pop(); @@ -260,7 +251,7 @@ Environment.prototype.get = function get(namespaceOrPath) { return this.store.get(namespace) || this.store.get(this.alias(namespace)) || - // namespace is empty if namespaceOrPath contains a win32 absolute path of the form 'C:\path\to\generator'. + // Namespace is empty if namespaceOrPath contains a win32 absolute path of the form 'C:\path\to\generator'. // for this reason we pass namespaceOrPath to the getByPath function. this.getByPath(namespaceOrPath); }; @@ -272,7 +263,7 @@ Environment.prototype.get = function get(namespaceOrPath) { */ Environment.prototype.getByPath = function (path) { if (fs.existsSync(path)) { - var namespace = this.namespace(path); + const namespace = this.namespace(path); this.register(path, namespace); return this.get(namespace); @@ -289,11 +280,10 @@ Environment.prototype.getByPath = function (path) { * @param {String} namespace * @param {Object} options */ - Environment.prototype.create = function create(namespace, options) { options = options || {}; - var Generator = this.get(namespace); + const Generator = this.get(namespace); if (!_.isFunction(Generator)) { return this.error( @@ -321,14 +311,13 @@ Environment.prototype.create = function create(namespace, options) { * @param {Array|String} options.arguments Arguments to pass the instance * @param {Object} options.options Options to pass the instance */ - Environment.prototype.instantiate = function instantiate(Generator, options) { options = options || {}; - var args = options.arguments || options.args || _.clone(this.arguments); + let args = options.arguments || options.args || _.clone(this.arguments); args = Array.isArray(args) ? args : args.split(' '); - var opts = options.options || _.clone(this.options); + const opts = options.options || _.clone(this.options); opts.env = this; opts.resolved = Generator.resolved || 'unknown'; @@ -346,7 +335,6 @@ Environment.prototype.instantiate = function instantiate(Generator, options) { * @param {Object} options * @param {Function} done */ - Environment.prototype.run = function run(args, options, done) { args = args || this.arguments; @@ -364,14 +352,14 @@ Environment.prototype.run = function run(args, options, done) { args = Array.isArray(args) ? args : args.split(' '); options = options || this.options; - var name = args.shift(); + const name = args.shift(); if (!name) { return this.error(new Error('Must provide at least one argument, the generator namespace to invoke.')); } - var generator = this.create(name, { - args: args, - options: options + const generator = this.create(name, { + args, + options }); if (generator instanceof Error) { @@ -404,36 +392,35 @@ Environment.prototype.run = function run(args, options, done) { * * @param {String} filepath */ - Environment.prototype.namespace = function namespace(filepath) { if (!filepath) { throw new Error('Missing namespace'); } - // cleanup extension and normalize path for differents OS - var ns = path.normalize(filepath.replace(new RegExp(escapeStrRe(path.extname(filepath)) + '$'), '')); + // Cleanup extension and normalize path for differents OS + let ns = path.normalize(filepath.replace(new RegExp(escapeStrRe(path.extname(filepath)) + '$'), '')); // Sort lookups by length so biggest are removed first - var lookups = _(this.lookups.concat(['..'])).map(path.normalize).sortBy('length').value().reverse(); + const lookups = _(this.lookups.concat(['..'])).map(path.normalize).sortBy('length').value().reverse(); - // if `ns` contains a lookup dir in its path, remove it. - ns = lookups.reduce(function (ns, lookup) { - // only match full directory (begin with leading slash or start of input, end with trailing slash) + // If `ns` contains a lookup dir in its path, remove it. + ns = lookups.reduce((ns, lookup) => { + // Only match full directory (begin with leading slash or start of input, end with trailing slash) lookup = new RegExp('(?:\\\\|/|^)' + escapeStrRe(lookup) + '(?=\\\\|/)', 'g'); return ns.replace(lookup, ''); }, ns); - var folders = ns.split(path.sep); - var scope = _.findLast(folders, function (folder) { + const folders = ns.split(path.sep); + const scope = _.findLast(folders, folder => { return folder.indexOf('@') === 0; }); - // cleanup `ns` from unwanted parts and then normalize slashes to `:` + // Cleanup `ns` from unwanted parts and then normalize slashes to `:` ns = ns - .replace(/(.*generator-)/, '') // remove before `generator-` - .replace(/[\/\\](index|main)$/, '') // remove `/index` or `/main` - .replace(/^[\/\\]+/, '') // remove leading `/` - .replace(/[\/\\]+/g, ':'); // replace slashes by `:` + .replace(/(.*generator-)/, '') // Remove before `generator-` + .replace(/[\/\\](index|main)$/, '') // Remove `/index` or `/main` + .replace(/^[\/\\]+/, '') // Remove leading `/` + .replace(/[\/\\]+/g, ':'); // Replace slashes by `:` if (scope) { ns = scope + '/' + ns; @@ -449,7 +436,6 @@ Environment.prototype.namespace = function namespace(filepath) { * @param {String} moduleId - Filepath or module name * @return {String} - The resolved path leading to the module */ - Environment.prototype.resolveModulePath = function resolveModulePath(moduleId) { if (moduleId[0] === '.') { moduleId = path.resolve(moduleId); @@ -467,7 +453,6 @@ Environment.prototype.resolveModulePath = function resolveModulePath(moduleId) { * @param {Environment} env * @return {Environment} The updated env */ - Environment.enforceUpdate = function (env) { if (!env.adapter) { env.adapter = new TerminalAdapter(); @@ -501,10 +486,7 @@ Environment.enforceUpdate = function (env) { * * @return {Environment} a new Environment instance */ - -Environment.createEnv = function (args, opts, adapter) { - return new Environment(args, opts, adapter); -}; +Environment.createEnv = (args, opts, adapter) => new Environment(args, opts, adapter); /** * Convert a generators namespace to its name @@ -512,14 +494,10 @@ Environment.createEnv = function (args, opts, adapter) { * @param {String} namespace * @return {String} */ - -Environment.namespaceToName = function (namespace) { - return namespace.split(':')[0]; -}; +Environment.namespaceToName = namespace => namespace.split(':')[0]; /** * Expose the utilities on the module * @see {@link env/util} */ - Environment.util = require('./util/util'); diff --git a/lib/resolver.js b/lib/resolver.js index 6b95bc48..e78e961a 100644 --- a/lib/resolver.js +++ b/lib/resolver.js @@ -1,17 +1,17 @@ 'use strict'; -var path = require('path'); -var fs = require('fs'); -var _ = require('lodash'); -var globby = require('globby'); -var debug = require('debug')('yeoman:environment'); +const path = require('path'); +const fs = require('fs'); +const _ = require('lodash'); +const globby = require('globby'); +const debug = require('debug')('yeoman:environment'); -var win32 = process.platform === 'win32'; +const win32 = process.platform === 'win32'; /** * @mixin * @alias env/resolver */ -var resolver = module.exports; +const resolver = module.exports; /** * Search for generators and their sub generators. @@ -29,24 +29,23 @@ var resolver = module.exports; * @param {function} cb - Callback called once the lookup is done. Take err as first * parameter. */ - resolver.lookup = function (cb) { - var generatorsModules = this.findGeneratorsIn(this.getNpmPaths()); - var patterns = []; + const generatorsModules = this.findGeneratorsIn(this.getNpmPaths()); + const patterns = []; - this.lookups.forEach(function (lookup) { - generatorsModules.forEach(function (modulePath) { + for (const lookup of this.lookups) { + for (const modulePath of generatorsModules) { patterns.push(path.join(modulePath, lookup)); - }); - }); + } + } - patterns.forEach(function (pattern) { - globby.sync('*/index.js', { cwd: pattern }).forEach(function (filename) { + for (const pattern of patterns) { + for (const filename of globby.sync('*/index.js', {cwd: pattern})) { this._tryRegistering(path.join(pattern, filename)); - }, this); - }, this); + } + } - if (_.isFunction(cb)) { + if (typeof cb === 'function') { return cb(null); } }; @@ -59,11 +58,10 @@ resolver.lookup = function (cb) { * @param {Array} List of search paths * @return {Array} List of the generator modules path */ - resolver.findGeneratorsIn = function (searchPaths) { - var modules = []; + let modules = []; - searchPaths.forEach(function (root) { + for (const root of searchPaths) { if (!root) { return; } @@ -71,10 +69,10 @@ resolver.findGeneratorsIn = function (searchPaths) { modules = globby.sync([ 'generator-*', '@*/generator-*' - ], { cwd: root }).map(function (match) { - return path.join(root, match); - }).concat(modules); - }); + ], {cwd: root}) + .map(match => path.join(root, match)) + .concat(modules); + } return modules; }; @@ -84,10 +82,9 @@ resolver.findGeneratorsIn = function (searchPaths) { * @private * @param {String} generatorReference A generator reference, usually a file path. */ - resolver._tryRegistering = function (generatorReference) { - var namespace; - var realPath = fs.realpathSync(generatorReference); + let namespace; + const realPath = fs.realpathSync(generatorReference); try { debug('found %s, trying to register', generatorReference); @@ -97,8 +94,8 @@ resolver._tryRegistering = function (generatorReference) { } this.register(realPath, namespace); - } catch (e) { - console.error('Unable to register %s (Error: %s)', generatorReference, e.message); + } catch (err) { + console.error('Unable to register %s (Error: %s)', generatorReference, err.message); } }; @@ -107,7 +104,7 @@ resolver._tryRegistering = function (generatorReference) { * @return {Array} lookup paths */ resolver.getNpmPaths = function () { - var paths = []; + let paths = []; // Add NVM prefix directory if (process.env.NVM_PATH) { @@ -126,7 +123,7 @@ resolver.getNpmPaths = function () { paths.push(path.join(__dirname, '../../../..')); paths.push(path.join(__dirname, '../..')); - // adds support for generator resolving when yeoman-generator has been linked + // Adds support for generator resolving when yeoman-generator has been linked if (process.argv[1]) { paths.push(path.join(path.dirname(process.argv[1]), '../..')); } @@ -140,11 +137,11 @@ resolver.getNpmPaths = function () { } // Walk up the CWD and add `node_modules/` folder lookup on each level - process.cwd().split(path.sep).forEach(function (part, i, parts) { - var lookup = path.join.apply(path, parts.slice(0, i + 1).concat(['node_modules'])); + process.cwd().split(path.sep).forEach((part, i, parts) => { + let lookup = path.join.apply(path, parts.slice(0, i + 1).concat(['node_modules'])); if (!win32) { - lookup = '/' + lookup; + lookup = `/${lookup}`; } paths.push(lookup); @@ -182,19 +179,18 @@ resolver.getNpmPaths = function () { * env.alias('foo'); * // => generator-foo:all */ - -resolver.alias = function alias(match, value) { +resolver.alias = function (match, value) { if (match && value) { this.aliases.push({ - match: match instanceof RegExp ? match : new RegExp('^' + match + '$'), - value: value + match: match instanceof RegExp ? match : new RegExp(`^${match}$`), + value }); return this; } - var aliases = this.aliases.slice(0).reverse(); + const aliases = this.aliases.slice(0).reverse(); - return aliases.reduce(function (res, alias) { + return aliases.reduce((res, alias) => { if (!alias.match.test(res)) { return res; } diff --git a/lib/store.js b/lib/store.js index 23009ba3..5a87f606 100644 --- a/lib/store.js +++ b/lib/store.js @@ -1,5 +1,4 @@ 'use strict'; -var _ = require('lodash'); /** * The Generator store @@ -8,8 +7,7 @@ var _ = require('lodash'); * @constructor * @private */ - -var Store = module.exports = function Store() { +const Store = module.exports = function Store() { this._generators = {}; this._meta = {}; }; @@ -19,9 +17,8 @@ var Store = module.exports = function Store() { * @param {String} namespace - The key under which the generator can be retrieved * @param {String|Function} generator - A generator module or a module path */ - Store.prototype.add = function add(namespace, generator) { - if (_.isString(generator)) { + if (typeof generator === 'string') { this._storeAsPath(namespace, generator); return; } @@ -32,12 +29,12 @@ Store.prototype.add = function add(namespace, generator) { Store.prototype._storeAsPath = function _storeAsPath(namespace, path) { this._meta[namespace] = { resolved: path, - namespace: namespace + namespace }; Object.defineProperty(this._generators, namespace, { - get: function () { - var Generator = require(path); + get() { + const Generator = require(path); return Generator; }, enumerable: true, @@ -48,7 +45,7 @@ Store.prototype._storeAsPath = function _storeAsPath(namespace, path) { Store.prototype._storeAsModule = function _storeAsModule(namespace, Generator) { this._meta[namespace] = { resolved: 'unknown', - namespace: namespace + namespace }; this._generators[namespace] = Generator; @@ -61,13 +58,13 @@ Store.prototype._storeAsModule = function _storeAsModule(namespace, Generator) { */ Store.prototype.get = function get(namespace) { - var Generator = this._generators[namespace]; + const Generator = this._generators[namespace]; if (!Generator) { return; } - return _.extend(Generator, this._meta[namespace]); + return Object.assign(Generator, this._meta[namespace]); }; /** diff --git a/lib/util/log.js b/lib/util/log.js index 445aaaa2..b6042f80 100644 --- a/lib/util/log.js +++ b/lib/util/log.js @@ -1,19 +1,18 @@ /** @module env/log */ 'use strict'; - -var util = require('util'); -var events = require('events'); -var _ = require('lodash'); -var table = require('text-table'); -var chalk = require('chalk'); -var logSymbols = require('log-symbols'); - -// padding step -var step = ' '; -var padding = ' '; - -// color -> status mappings -var colors = { +const util = require('util'); +const EventEmitter = require('events'); +const _ = require('lodash'); +const table = require('text-table'); +const chalk = require('chalk'); +const logSymbols = require('log-symbols'); + +// Padding step +const step = ' '; +let padding = ' '; + +// Color -> status mappings +const colors = { skip: 'yellow', force: 'yellow', create: 'green', @@ -24,16 +23,16 @@ var colors = { }; function pad(status) { - var max = 'identical'.length; - var delta = max - status.length; - return delta ? new Array(delta + 1).join(' ') + status : status; + const max = 'identical'.length; + const delta = max - status.length; + return delta ? ' '.repeat(delta) + status : status; } -// borrowed from https://github.com/mikeal/logref/blob/master/main.js#L6-15 +// Borrowed from https://github.com/mikeal/logref/blob/master/main.js#L6-15 function formatter(msg, ctx) { while (msg.indexOf('%') !== -1) { - var start = msg.indexOf('%'); - var end = msg.indexOf(' ', start); + const start = msg.indexOf('%'); + let end = msg.indexOf(' ', start); if (end === -1) { end = msg.length; @@ -45,7 +44,7 @@ function formatter(msg, ctx) { return msg; } -module.exports = function logger() { +module.exports = () => { // `this.log` is a [logref](https://github.com/mikeal/logref) // compatible logger, with an enhanced API. // @@ -75,7 +74,7 @@ module.exports = function logger() { return log; } - _.extend(log, events.EventEmitter.prototype); + _.extend(log, EventEmitter.prototype); // A simple write method, with formatted message. // @@ -105,15 +104,17 @@ module.exports = function logger() { return this; }; - log.on('up', function () { - padding = padding + step; + log.on('up', () => { + padding += step; }); - log.on('down', function () { + log.on('down', () => { padding = padding.replace(step, ''); }); - Object.keys(colors).forEach(function (status) { + // eslint-disable no-loop-func + // TODO: Fix this ESLint warning + for (const status of Object.keys(colors)) { // Each predefined status has its logging method utility, handling // status color and padding before the usual `.write()` // @@ -139,12 +140,13 @@ module.exports = function logger() { // // Returns the logger log[status] = function () { - var color = colors[status]; + const color = colors[status]; this.write(chalk[color](pad(status))).write(padding); this.write(util.format.apply(util, arguments) + '\n'); return this; }; - }); + } + // eslint-enable no-loop-func // A basic wrapper around `cli-table` package, resetting any single // char to empty strings, this is used for aligning options and @@ -154,15 +156,15 @@ module.exports = function logger() { // table. // // Returns the table reprensetation - log.table = function (opts) { - var tableData = []; + log.table = opts => { + const tableData = []; - opts = Array.isArray(opts) ? { rows: opts } : opts; + opts = Array.isArray(opts) ? {rows: opts} : opts; opts.rows = opts.rows || []; - opts.rows.forEach(function (row) { + for (const row of opts.rows) { tableData.push(row); - }); + } return table(tableData); }; diff --git a/lib/util/util.js b/lib/util/util.js index 9d95a579..ba4f9f36 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -1,7 +1,6 @@ /** @module env/util */ 'use strict'; - -var GroupedQueue = require('grouped-queue'); +const GroupedQueue = require('grouped-queue'); /** * Create a "sloppy" copy of an initial Environment object. The focus of this method is on @@ -13,11 +12,10 @@ var GroupedQueue = require('grouped-queue'); * @param {Environment} initialEnv - an Environment instance * @return {Environment} sloppy copy of the initial Environment */ - -exports.duplicateEnv = function (initialEnv) { - var queues = require('../environment').queues; +exports.duplicateEnv = initialEnv => { + const queues = require('../environment').queues; // Hack: create a clone of the environment with a new instance of runLoop - var env = Object.create(initialEnv); + const env = Object.create(initialEnv); env.runLoop = new GroupedQueue(queues); return env; }; diff --git a/package.json b/package.json index d7714464..0085e382 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "license": "BSD-2-Clause", "repository": "yeoman/environment", "scripts": { - "test": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", + "test": "gulp", "doc": "jsdoc -c ./jsdoc.json ./readme.md", "benchmark": "matcha benchmark/**", "prepublish": "gulp prepublish" @@ -47,10 +47,7 @@ "coveralls": "^2.11.6", "gulp": "^3.6.0", "gulp-coveralls": "^0.1.0", - "gulp-eslint": "^3.0.1", - "gulp-exclude-gitignore": "^1.0.0", "gulp-istanbul": "^1.1.1", - "gulp-jscs": "^4.0.0", "gulp-mocha": "^3.0.1", "gulp-nsp": "^2.1.0", "gulp-plumber": "^1.0.0", @@ -62,5 +59,12 @@ "sinon": "^1.9.1", "yeoman-assert": "^3.0.0", "yeoman-generator": "^1.1.0" + }, + "xo": { + "space": true, + "envs": [ + "node", + "mocha" + ] } } diff --git a/readme.md b/readme.md index 06bdf635..59186cd5 100644 --- a/readme.md +++ b/readme.md @@ -6,6 +6,7 @@ It provides a high-level API to discover, create and run generators, as well as further tuning of where and how a generator is resolved. + ## Install ``` @@ -15,16 +16,16 @@ $ npm install --save yeoman-environment ## Usage -Full documentation available at http://yeoman.io/authoring/integrating-yeoman.html +Full documentation available [here](http://yeoman.io/authoring/integrating-yeoman.html). ```js -var yeoman = require('yeoman-environment'); -var env = yeoman.createEnv(); +const yeoman = require('yeoman-environment'); +const env = yeoman.createEnv(); -// The #lookup() method will search the user computer for installed generators. -// The search if done from the current working directory. -env.lookup(function () { - env.run('angular', {'skip-install': true}, function (err) { +// The #lookup() method will search the user computer for installed generators +// The search if done from the current working directory +env.lookup(() => { + env.run('angular', {'skip-install': true}, err => { console.log('done'); }); }); @@ -35,4 +36,4 @@ For advance usage, see [our API documentation](http://yeoman.github.io/environme ## License -BSD © Yeoman +BSD-2-Clause © Yeoman diff --git a/test/adapter.js b/test/adapter.js index fef8a898..9dc1591d 100644 --- a/test/adapter.js +++ b/test/adapter.js @@ -1,17 +1,16 @@ 'use strict'; -var assert = require('yeoman-assert'); -var _ = require('lodash'); -var inquirer = require('inquirer'); -var sinon = require('sinon'); -var logSymbols = require('log-symbols'); -var TerminalAdapter = require('../lib/adapter'); - -describe('TerminalAdapter', function () { +const assert = require('yeoman-assert'); +const inquirer = require('inquirer'); +const sinon = require('sinon'); +const logSymbols = require('log-symbols'); +const TerminalAdapter = require('../lib/adapter'); + +describe('TerminalAdapter', () => { beforeEach(function () { this.adapter = new TerminalAdapter(); }); - describe('#prompt()', function () { + describe('#prompt()', () => { beforeEach(function () { this.sandbox = sinon.sandbox.create(); this.fakePromise = {then: sinon.spy()}; @@ -25,38 +24,38 @@ describe('TerminalAdapter', function () { }); it('pass its arguments to inquirer', function () { - var questions = []; - var func = function () {}; - var ret = this.adapter.prompt(questions, func); + const questions = []; + const func = () => {}; + const ret = this.adapter.prompt(questions, func); sinon.assert.calledWith(this.stub, questions); sinon.assert.calledWith(this.fakePromise.then, func); assert.equal(ret, this.fakePromise); }); }); - describe('#diff()', function () { + describe('#diff()', () => { it('returns properly colored diffs', function () { - var diff = this.adapter.diff('var', 'let'); - assert.textEqual(diff, '\n\u001b[41mremoved\u001b[49m \u001b[30m\u001b[42madded\u001b[49m\u001b[39m\n\n\u001b[41mvar\u001b[49m\u001b[30m\u001b[42mlet\u001b[49m\u001b[39m\n'); + const diff = this.adapter.diff('var', 'let'); + assert.textEqual(diff, '\n\u001B[41mremoved\u001B[49m \u001B[30m\u001B[42madded\u001B[49m\u001B[39m\n\n\u001B[41mvar\u001B[49m\u001B[30m\u001B[42mlet\u001B[49m\u001B[39m\n'); }); }); - describe('#log()', function () { - var logMessage; - var stderrWriteBackup = process.stderr.write; + describe('#log()', () => { + let logMessage; + const stderrWriteBackup = process.stderr.write; beforeEach(function () { this.spyerror = sinon.spy(console, 'error'); logMessage = ''; - process.stderr.write = (function () { - return function (str) { + process.stderr.write = (() => { + return str => { logMessage = str; }; - }(process.stderr.write)); + })(process.stderr.write); }); - afterEach(function () { + afterEach(() => { console.error.restore(); process.stderr.write = stderrWriteBackup; }); @@ -90,7 +89,7 @@ describe('TerminalAdapter', function () { }); it('#write() objects', function () { - var outputObject = { + const outputObject = { something: 72, another: 12 }; @@ -99,20 +98,19 @@ describe('TerminalAdapter', function () { assert(this.spyerror.withArgs(outputObject).calledOnce); assert.equal(logMessage, '{ something: 72, another: 12 }\n'); }); - }); - describe('#log', function () { + describe('#log', () => { beforeEach(function () { this.spylog = sinon.spy(process.stderr, 'write'); }); - afterEach(function () { + afterEach(() => { process.stderr.write.restore(); }); it('#write() pass strings as they are', function () { - var testString = 'dummy'; + const testString = 'dummy'; this.adapter.log.write(testString); assert(this.spylog.withArgs(testString).calledOnce); }); @@ -130,15 +128,15 @@ describe('TerminalAdapter', function () { it('#ok() adds a green "✔ " at the beginning and \\n at the end', function () { this.adapter.log.ok('dummy'); - assert(this.spylog.withArgs(logSymbols.success + ' dummy\n').calledOnce); + assert(this.spylog.withArgs(`${logSymbols.success} dummy\n`).calledOnce); }); it('#error() adds a green "✗ " at the beginning and \\n at the end', function () { this.adapter.log.error('dummy'); - assert(this.spylog.withArgs(logSymbols.error + ' dummy\n').calledOnce); + assert(this.spylog.withArgs(`${logSymbols.error} dummy\n`).calledOnce); }); - describe('statuses', function () { + describe('statuses', () => { it('#skip()'); it('#force()'); it('#create()'); diff --git a/test/environment.js b/test/environment.js index 24a59848..a9bb837f 100644 --- a/test/environment.js +++ b/test/environment.js @@ -1,15 +1,13 @@ -/*global it, describe, before, beforeEach, afterEach */ -/*jshint scripturl: true */ 'use strict'; -var events = require('events'); -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var sinon = require('sinon'); -var Generator = require('yeoman-generator'); -var assert = require('yeoman-assert'); -var TerminalAdapter = require('../lib/adapter'); -var Environment = require('../lib/environment'); +const events = require('events'); +const fs = require('fs'); +const path = require('path'); +const util = require('util'); +const sinon = require('sinon'); +const Generator = require('yeoman-generator'); +const assert = require('yeoman-assert'); +const TerminalAdapter = require('../lib/adapter'); +const Environment = require('../lib/environment'); describe('Environment', function () { beforeEach(function () { diff --git a/test/fixtures/generator-simple/index.js b/test/fixtures/generator-simple/index.js index 44ce75df..fa44d12c 100644 --- a/test/fixtures/generator-simple/index.js +++ b/test/fixtures/generator-simple/index.js @@ -1,4 +1,4 @@ -module.exports = function(args, options) { +module.exports = (args, options) => { console.log('Executing generator with', args, options); }; diff --git a/test/resolver.js b/test/resolver.js index db400372..65405310 100644 --- a/test/resolver.js +++ b/test/resolver.js @@ -1,30 +1,30 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var assert = require('assert'); -var shell = require('shelljs'); -var Environment = require('../lib/environment'); +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); +const shell = require('shelljs'); +const Environment = require('../lib/environment'); -var globalLookupTest = process.env.NODE_PATH ? it : xit; +const globalLookupTest = process.env.NODE_PATH ? it : xit; describe('Environment Resolver', function () { this.timeout(100000); - describe('#lookup()', function () { - var scopedFolder = path.resolve('./node_modules/@dummyscope'); - var scopedGenerator = path.join(scopedFolder, 'generator-scoped'); + describe('#lookup()', () => { + const scopedFolder = path.resolve('node_modules/@dummyscope'); + const scopedGenerator = path.join(scopedFolder, 'generator-scoped'); before(function () { this.projectRoot = path.join(__dirname, 'fixtures/lookup-project'); process.chdir(this.projectRoot); - shell.exec('npm install', { silent: true }); - shell.exec('npm install generator-jquery', { silent: true }); - shell.exec('npm install -g generator-dummytest generator-dummy', { silent: true }); + shell.exec('npm install', {silent: true}); + shell.exec('npm install generator-jquery', {silent: true}); + shell.exec('npm install -g generator-dummytest generator-dummy', {silent: true}); fs.symlinkSync( - path.resolve('../generator-extend'), - path.resolve('./node_modules/generator-extend'), - 'dir' + path.resolve('../generator-extend'), + path.resolve('node_modules/generator-extend'), + 'dir' ); if (!fs.existsSync(scopedFolder)) { @@ -33,15 +33,15 @@ describe('Environment Resolver', function () { if (!fs.existsSync(scopedGenerator)) { fs.symlinkSync( - path.resolve('../generator-scoped'), - scopedGenerator, - 'dir' + path.resolve('../generator-scoped'), + scopedGenerator, + 'dir' ); } }); after(function () { - fs.unlinkSync(path.join(this.projectRoot, './node_modules/generator-extend')); + fs.unlinkSync(path.join(this.projectRoot, 'node_modules/generator-extend')); fs.unlinkSync(scopedGenerator); fs.rmdirSync(scopedFolder); process.chdir(__dirname); @@ -67,8 +67,7 @@ describe('Environment Resolver', function () { }); if (!process.env.NODE_PATH) { - console.log('Skipping tests for global generators. Please setup `NODE_PATH` ' + - 'environment variable to run it.'); + console.log('Skipping tests for global generators. Please setup `NODE_PATH` environment variable to run it.'); } it('local generators prioritized over global', function () { @@ -84,11 +83,11 @@ describe('Environment Resolver', function () { assert.ok(this.env.get('extend:support')); }); - describe('when there\'s ancestor node_modules/ folder', function () { + describe('when there\'s ancestor node_modules/ folder', () => { before(function () { this.projectSubRoot = path.join(this.projectRoot, 'subdir'); process.chdir(this.projectSubRoot); - shell.exec('npm install', { silent: true }); + shell.exec('npm install', {silent: true}); }); beforeEach(function () { @@ -107,7 +106,7 @@ describe('Environment Resolver', function () { }); }); - describe('#getNpmPaths()', function () { + describe('#getNpmPaths()', () => { beforeEach(function () { this.NODE_PATH = process.env.NODE_PATH; this.bestBet = path.join(__dirname, '../../../..'); @@ -119,17 +118,17 @@ describe('Environment Resolver', function () { process.env.NODE_PATH = this.NODE_PATH; }); - describe('with NODE_PATH', function () { - beforeEach(function () { + describe('with NODE_PATH', () => { + beforeEach(() => { process.env.NODE_PATH = '/some/dummy/path'; }); - afterEach(function () { + afterEach(() => { delete process.env.NODE_PATH; }); it('walk up the CWD lookups dir', function () { - var paths = this.env.getNpmPaths(); + const paths = this.env.getNpmPaths(); assert.equal(paths[0], path.join(process.cwd(), 'node_modules')); assert.equal(paths[1], path.join(process.cwd(), '../node_modules')); }); @@ -139,15 +138,15 @@ describe('Environment Resolver', function () { }); }); - describe('without NODE_PATH', function () { - beforeEach(function () { + describe('without NODE_PATH', () => { + beforeEach(() => { delete process.env.NODE_PATH; }); it('walk up the CWD lookups dir', function () { - var paths = this.env.getNpmPaths(); + const paths = this.env.getNpmPaths(); assert.equal(paths[0], path.join(process.cwd(), 'node_modules')); - var prevdir = process.cwd().split(path.sep).slice(0, -1).join(path.sep); + const prevdir = process.cwd().split(path.sep).slice(0, -1).join(path.sep); assert.equal(paths[1], path.join(prevdir, 'node_modules')); }); @@ -165,17 +164,17 @@ describe('Environment Resolver', function () { }); }); - describe('with NVM_PATH', function () { - beforeEach(function () { + describe('with NVM_PATH', () => { + beforeEach(() => { process.env.NVM_PATH = '/some/dummy/path'; }); - afterEach(function () { + afterEach(() => { delete process.env.NVM_PATH; }); it('walk up the CWD lookups dir', function () { - var paths = this.env.getNpmPaths(); + const paths = this.env.getNpmPaths(); assert.equal(paths[0], path.join(process.cwd(), 'node_modules')); assert.equal(paths[1], path.join(process.cwd(), '../node_modules')); }); @@ -185,13 +184,13 @@ describe('Environment Resolver', function () { }); }); - describe('without NVM_PATH', function () { - beforeEach(function () { + describe('without NVM_PATH', () => { + beforeEach(() => { delete process.env.NVM_PATH; }); it('walk up the CWD lookups dir', function () { - var paths = this.env.getNpmPaths(); + const paths = this.env.getNpmPaths(); assert.equal(paths[0], path.join(process.cwd(), 'node_modules')); assert.equal(paths[1], path.join(process.cwd(), '../node_modules')); }); @@ -201,6 +200,5 @@ describe('Environment Resolver', function () { assert(this.env.getNpmPaths().indexOf(this.bestBet2) >= 0); }); }); - }); }); diff --git a/test/store.js b/test/store.js index 57482fc9..4303b8a5 100644 --- a/test/store.js +++ b/test/store.js @@ -1,20 +1,20 @@ 'use strict'; -var assert = require('assert'); -var path = require('path'); -var Store = require('../lib/store'); +const assert = require('assert'); +const path = require('path'); +const Store = require('../lib/store'); -describe('Store', function () { +describe('Store', () => { beforeEach(function () { this.store = new Store(); }); - describe('#add() / #get()', function () { + describe('#add() / #get()', () => { beforeEach(function () { this.modulePath = path.join(__dirname, 'fixtures/generator-mocha'); this.module = require(this.modulePath); }); - describe('storing as module', function () { + describe('storing as module', () => { beforeEach(function () { this.store.add('foo:module', this.module); this.outcome = this.store.get('foo:module'); @@ -33,7 +33,7 @@ describe('Store', function () { }); }); - describe('storing as module path', function () { + describe('storing as module path', () => { beforeEach(function () { this.store.add('foo:path', this.modulePath); this.outcome = this.store.get('foo:path'); @@ -51,7 +51,7 @@ describe('Store', function () { }); }); - describe('#namespaces()', function () { + describe('#namespaces()', () => { beforeEach(function () { this.store.add('foo', {}); this.store.add('lab', {}); diff --git a/test/util.js b/test/util.js index 17f83fcf..f9a50837 100644 --- a/test/util.js +++ b/test/util.js @@ -1,18 +1,18 @@ 'use strict'; -var assert = require('assert'); -var util = require('../lib/util/util'); -var Env = require('../'); +const assert = require('assert'); +const util = require('../lib/util/util'); +const Env = require('..'); -describe('util', function () { - it('is exposed on the Environment object', function () { +describe('util', () => { + it('is exposed on the Environment object', () => { assert.equal(Env.util, util); }); - describe('.duplicateEnv()', function () { - it('copy environment', function () { - var env = new Env(); - var clone = util.duplicateEnv(env); - assert(env.isPrototypeOf(clone)); + describe('.duplicateEnv()', () => { + it('copy environment', () => { + const env = new Env(); + const clone = util.duplicateEnv(env); + assert(Object.prototype.isPrototypeOf.call(env, clone)); assert.notEqual(clone.runLoop, env.runLoop); }); });