yeoman-generator
Advanced tools
Comparing version 0.13.4 to 0.14.0-rc.1
@@ -75,13 +75,4 @@ var logger = process.logging || require('../util/log'); | ||
/** | ||
* Make some of the file API aware of our source/destination root paths. | ||
* `copy`, `template` (only when could be applied/required by legacy code), | ||
* `write` and alike consider. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
actions.copy = function copy(source, destination, process) { | ||
// Copy helper for two versions of copy action | ||
function prepCopy(source, destination, process) { | ||
var body; | ||
@@ -111,4 +102,26 @@ destination = destination || source; | ||
return { | ||
body: body, | ||
encoding: encoding, | ||
destination: destination, | ||
source: source | ||
}; | ||
}; | ||
/** | ||
* Make some of the file API aware of our source/destination root paths. | ||
* `copy`, `template` (only when could be applied/required by legacy code), | ||
* `write` and alike consider. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
actions.copy = function copy(source, destination, process) { | ||
var file = prepCopy.call(this, source, destination, process); | ||
try { | ||
body = this.engine(body, this); | ||
file.body = this.engine(file.body, this); | ||
} catch (err) { | ||
@@ -119,3 +132,3 @@ // this happens in some cases when trying to copy a JS file like lodash/underscore | ||
this.checkForCollision(destination, body, function (err, config) { | ||
this.checkForCollision(file.destination, file.body, function (err, config) { | ||
var stats; | ||
@@ -134,12 +147,12 @@ | ||
mkdirp.sync(path.dirname(destination)); | ||
fs.writeFileSync(destination, body); | ||
mkdirp.sync(path.dirname(file.destination)); | ||
fs.writeFileSync(file.destination, file.body); | ||
// synchronize stats and modification times from the original file. | ||
stats = fs.statSync(source); | ||
stats = fs.statSync(file.source); | ||
try { | ||
fs.chmodSync(destination, stats.mode); | ||
fs.utimesSync(destination, stats.atime, stats.mtime); | ||
fs.chmodSync(file.destination, stats.mode); | ||
fs.utimesSync(file.destination, stats.atime, stats.mtime); | ||
} catch (err) { | ||
this.log.error('Error setting permissions of "' + chalk.bold(destination) + '" file: ' + err); | ||
this.log.error('Error setting permissions of "' + chalk.bold(file.destination) + '" file: ' + err); | ||
} | ||
@@ -154,2 +167,35 @@ | ||
/** | ||
* Bulk copy | ||
* https://github.com/yeoman/generator/pull/359 | ||
* https://github.com/yeoman/generator/issues/350 | ||
* | ||
* An optimized copy method for larger file trees. Does not do | ||
* full conflicter checks, only check ir root directory is not empty. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
actions.bulkCopy = function bulkCopy(source, destination, process) { | ||
var file = prepCopy.call(this, source, destination, process); | ||
mkdirp.sync(path.dirname(file.destination)); | ||
fs.writeFileSync(file.destination, file.body); | ||
// synchronize stats and modification times from the original file. | ||
stats = fs.statSync(file.source); | ||
try { | ||
fs.chmodSync(file.destination, stats.mode); | ||
fs.utimesSync(file.destination, stats.atime, stats.mtime); | ||
} catch (err) { | ||
this.log.error('Error setting permissions of "' + chalk.bold(file.destination) + '" file: ' + err); | ||
} | ||
log.create(file.destination); | ||
return this; | ||
}; | ||
/** | ||
* A simple method to read the content of the a file borrowed from Grunt: | ||
@@ -300,14 +346,6 @@ * https://github.com/gruntjs/grunt/blob/master/lib/grunt/file.js | ||
/** | ||
* Copies recursively the files from source directory to root directory. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
actions.directory = function directory(source, destination, process) { | ||
// Shared directory method | ||
function _directory(source, destination, process, bulk) { | ||
var root = path.join(this.sourceRoot(), source); | ||
var files = this.expandFiles('**', { dot: true, cwd: root }); | ||
var self = this; | ||
@@ -321,19 +359,48 @@ destination = destination || source; | ||
var cp = this.copy; | ||
if (bulk) { | ||
cp = this.bulkCopy; | ||
} | ||
// get the path relative to the template root, and copy to the relative destination | ||
var resolveFiles = function (filepath) { | ||
return function (next) { | ||
if (!filepath) { | ||
self.emit('directory:end'); | ||
return next(); | ||
} | ||
for (var i in files) { | ||
var dest = path.join(destination, files[i]); | ||
cp.call(this, path.join(root, files[i]), dest, process); | ||
} | ||
var dest = path.join(destination, filepath); | ||
self.copy(path.join(root, filepath), dest, process); | ||
return this; | ||
}; | ||
return next(); | ||
}; | ||
}; | ||
/** | ||
* Copies recursively the files from source directory to root directory. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
async.parallel(files.map(resolveFiles)); | ||
actions.directory = function directory(source, destination, process) { | ||
return _directory.call(this, source, destination, process); | ||
}; | ||
/** | ||
* Copies recursively the files from source directory to root directory. | ||
* | ||
* @param {String} source | ||
* @param {String} destination | ||
* @param {Function} process | ||
*/ | ||
actions.bulkDirectory = function directory(source, destination, process) { | ||
var self = this; | ||
this.checkForCollision(destination, null, function (err, config) { | ||
// create or force means file write, identical or skip prevent the | ||
// actual write. | ||
if (!(/force|create/.test(config.status))) { | ||
return config.callback(); | ||
} | ||
_directory.call(this, source, destination, process, true); | ||
config.callback(); | ||
}); | ||
return this; | ||
@@ -340,0 +407,0 @@ }; |
var fs = require('fs'); | ||
var tar = require('tar'); | ||
var path = require('path'); | ||
var zlib = require('zlib'); | ||
var request = require('request'); | ||
var download = require('download'); | ||
var chalk = require('chalk'); | ||
@@ -14,5 +12,5 @@ | ||
/** | ||
* Download a single file to a given destination. | ||
* Download a string or an array of files to a given destination. | ||
* | ||
* @param {String} url | ||
* @param {String|Array} url | ||
* @param {String} destination | ||
@@ -23,60 +21,44 @@ * @param {Function} cb | ||
fetch.fetch = function _fetch(url, destination, cb) { | ||
this.mkdir(path.dirname(destination)); | ||
var dl = download(url, destination, { proxy: proxy }); | ||
var log = this.log('... Fetching %s ...', url); | ||
fetch.request(url) | ||
.on('error', cb) | ||
return dl | ||
.on('data', function () { | ||
log.write('.'); | ||
}) | ||
.pipe(fs.createWriteStream(destination)) | ||
.on('error', cb) | ||
.on('close', function () { | ||
log.write('Writing ' + destination + '...'); | ||
}) | ||
.on('close', cb); | ||
.once('close', function () { | ||
log.ok('Done in ' + destination).write(); | ||
cb(); | ||
}); | ||
}; | ||
/** | ||
* Fetch a tarball and extract it to a given destination. | ||
* Fetch a string or an array of archives and extract it/them to a given | ||
* destination. | ||
* | ||
* @param {String} tarball | ||
* @param {String} target | ||
* @param {String|Array} archive | ||
* @param {String} destination | ||
* @param {Function} cb | ||
*/ | ||
fetch.tarball = function _tarball(tarball, target, cb) { | ||
var now = Date.now(); | ||
fetch.extract = function _extract(archive, destination, cb) { | ||
var opts = { | ||
extract: true, | ||
proxy: proxy, | ||
strip: 1 | ||
}; | ||
var dl = download(archive, destination, opts); | ||
var log = this.log.write() | ||
.info('... Fetching %s ...', tarball) | ||
.info('... Fetching %s ...', archive) | ||
.info(chalk.yellow('This might take a few moments')); | ||
var extractOpts = { type: 'Directory', path: target, strip: 1 }; | ||
var req = fetch.request.get(tarball).on('error', cb); | ||
req.on('data', function () { | ||
log.write('.'); | ||
}).on('end', function () { | ||
log.write().ok('Done in ' + (Date.now() - now) / 1000 + 's.'); | ||
}); | ||
req | ||
.pipe(zlib.Unzip()) | ||
.on('error', function (err) { | ||
console.error('unzip error', err); | ||
cb(err); | ||
return dl | ||
.on('data', function () { | ||
log.write('.'); | ||
}) | ||
.pipe(tar.Extract(extractOpts)) | ||
.on('entry', function (entry) { | ||
entry.props.uid = entry.uid = 501; | ||
entry.props.gid = entry.gid = 20; | ||
}) | ||
.on('error', function (err) { | ||
console.error('untar error', err); | ||
cb(err); | ||
}) | ||
.on('close', function () { | ||
log.ok('Done in ' + extractOpts.path).write(); | ||
.on('error', cb) | ||
.once('close', function () { | ||
log.ok('Done in ' + destination).write(); | ||
cb(); | ||
@@ -86,2 +68,2 @@ }); | ||
fetch.request = request.defaults({ proxy: proxy }); | ||
fetch.tarball = fetch.extract; |
@@ -83,3 +83,3 @@ var util = require('util'); | ||
var updatedContent = this.append(html, tagName, content); | ||
this.writeFileFromString(path, updatedContent); | ||
this.writeFileFromString(updatedContent, path); | ||
}; | ||
@@ -99,3 +99,3 @@ | ||
var updatedContent = this.prepend(html, tagName, content); | ||
this.writeFileFromString(path, updatedContent); | ||
this.writeFileFromString(updatedContent, path); | ||
}; | ||
@@ -102,0 +102,0 @@ |
@@ -321,4 +321,4 @@ var fs = require('fs'); | ||
var context = hook.as || self.resolved || self.generateName; | ||
var options = hook.options || self.options; | ||
options.args = hook.args || self.args; | ||
var options = _.clone(hook.options || self.options); | ||
options.args = _.clone(hook.args || self.args); | ||
@@ -465,13 +465,8 @@ return function (next) { | ||
Base.prototype.usage = function usage() { | ||
var args = this._arguments.map(function (arg) { | ||
return arg.config.banner; | ||
}).join(' '); | ||
var options = this._options.length ? '[options]' : ''; | ||
var name = this.generatorName ? ' ' + this.generatorName : ''; | ||
var options = this._options.length ? '[options]' : '', | ||
name = (this.namespace === 'yeoman:app' || !this.namespace) ? '' : this.namespace + ' ', | ||
cmd = 'init'; | ||
name = name.replace(/^yeoman:/, ''); | ||
var out = 'yeoman ' + cmd + ' ' + name + args + ' ' + options; | ||
var out = 'yo' + name + ' ' + options; | ||
@@ -535,3 +530,3 @@ if (this.description) { | ||
var path = findup('package.json', { cwd: this.resolved }); | ||
return JSON.parse(fs.readFileSync(path, 'utf8')).name; | ||
return path ? JSON.parse(fs.readFileSync(path, 'utf8')).name : '*'; | ||
}; | ||
@@ -538,0 +533,0 @@ |
128
lib/env.js
@@ -179,3 +179,3 @@ var fs = require('fs'); | ||
Object.keys(groups).forEach(function (key) { | ||
Object.keys(groups).sort().forEach(function (key) { | ||
var group = groups[key]; | ||
@@ -217,42 +217,24 @@ | ||
Environment.prototype.register = function register(name, namespace) { | ||
if (!name) { | ||
return this.error(new Error('You must provide a generator to register.')); | ||
if (!_.isString(name)) { | ||
return this.error(new Error('You must provide a generator name to register.')); | ||
} | ||
var cachePath = _.isString(name); | ||
var generator = cachePath ? function () {} : name; | ||
var isRaw = function (generator) { | ||
generator = Object.getPrototypeOf(generator.prototype); | ||
var methods = ['option', 'argument', 'hookFor', 'run']; | ||
return methods.filter(function (method) { | ||
return !!generator[method]; | ||
}).length !== methods.length; | ||
}; | ||
var filepath; | ||
var self = this; | ||
var filepath = name; | ||
var ns; | ||
if (cachePath) { | ||
filepath = name; | ||
if (filepath[0] === '.') { | ||
filepath = path.resolve(filepath); | ||
} | ||
if (filepath.charAt(0) === '.') { | ||
filepath = path.resolve(filepath); | ||
} | ||
if (filepath[0] === '~') { | ||
filepath = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] + filepath.slice(1); | ||
} | ||
if (filepath.charAt(0) === '~') { | ||
filepath = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] + filepath.slice(1); | ||
} | ||
var generatorProps = {}; | ||
generatorProps.resolved = require.resolve(filepath); | ||
generatorProps.namespace = this.namespace(generatorProps.resolved); | ||
generator.resolved = require.resolve(filepath); | ||
generator.namespace = this.namespace(generator.resolved); | ||
generator.__register = function () { | ||
var invokedGenerator = require(generator.resolved); | ||
invokedGenerator.resolved = generator.resolved; | ||
this.register(invokedGenerator, generator.namespace); | ||
}.bind(this); | ||
} | ||
ns = namespace || generatorProps.namespace || this.namespace(name); | ||
ns = namespace || generator.namespace || this.namespace(name); | ||
if (!ns) { | ||
@@ -269,11 +251,53 @@ return this.error(new Error('Unable to determine namespace.')); | ||
generator.namespace = ns; | ||
generator.raw = isRaw(generator); | ||
generator.resolved = generator.resolved || ns; | ||
this.generators[ns] = generator; | ||
Object.defineProperty(this.generators, ns, { | ||
get: function () { | ||
var Generator = require(generatorProps.resolved); | ||
Generator.resolved = generatorProps.resolved; | ||
Generator.namespace = generatorProps.namespace; | ||
return Generator; | ||
}, | ||
set: function (val) { | ||
Object.defineProperty(self.generators, ns, { | ||
value: val, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
debug('Registered %s (%s)', generator.namespace, generator.resolved); | ||
debug('Registered %s (%s)', generatorProps.namespace, generatorProps.resolved); | ||
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.')); | ||
} | ||
var isRaw = function (generator) { | ||
generator = Object.getPrototypeOf(generator.prototype); | ||
var methods = ['option', 'argument', 'hookFor', 'run']; | ||
return methods.filter(function (method) { | ||
return !!generator[method]; | ||
}).length !== methods.length; | ||
}; | ||
if (isRaw(Generator)) { | ||
var newGenerator = function () { | ||
Base.apply(this, arguments); | ||
}; | ||
util.inherits(newGenerator, Base); | ||
newGenerator.prototype.exec = Generator; | ||
Generator = newGenerator; | ||
} | ||
Generator.resolved = 'lorem'; | ||
this.generators[namespace] = Generator; | ||
return this; | ||
}; | ||
/** | ||
@@ -303,10 +327,3 @@ * Returns the list of registered namespace. | ||
var get = function (namespace) { | ||
var generator = this.generators[namespace]; | ||
if (generator) { | ||
if (generator.__register) { | ||
generator.__register(); | ||
generator = get(namespace); | ||
} | ||
return generator; | ||
} | ||
return this.generators[namespace]; | ||
}.bind(this); | ||
@@ -336,3 +353,3 @@ | ||
var generator = this.get(namespace); | ||
var Generator = this.get(namespace); | ||
@@ -344,3 +361,3 @@ var args = options.arguments || options.args || this.arguments; | ||
if (!generator) { | ||
if (!Generator) { | ||
return this.error( | ||
@@ -356,18 +373,5 @@ new Error( | ||
// case of raw functions, we create a brand new `Base` object and attach this | ||
// raw function as one of the prototype method. this effectively standardize | ||
// the interface for running generators, while allowing less boilerplate for | ||
// generators authors. | ||
var Generator = generator; | ||
if (generator.raw) { | ||
Generator = function () { | ||
Base.apply(this, arguments); | ||
}; | ||
util.inherits(Generator, Base); | ||
Generator.prototype.exec = generator; | ||
} | ||
opts.env = this; | ||
opts.name = name; | ||
opts.resolved = generator.resolved; | ||
opts.resolved = Generator.resolved; | ||
return new Generator(args, opts); | ||
@@ -374,0 +378,0 @@ }; |
@@ -142,2 +142,10 @@ var fs = require('fs'); | ||
helpers.assertTextEqual = function (value, expected) { | ||
function eol(str) { | ||
return str.replace(/\r\n/g, '\n'); | ||
} | ||
assert.equal(eol(value), eol(expected)); | ||
}; | ||
// Clean-up the test directory and ce into it. | ||
@@ -205,7 +213,7 @@ // Call given callback when you're there. | ||
// | ||
helpers.createGenerator = function (name, dependencies, args) { | ||
helpers.createGenerator = function (name, dependencies, args, options) { | ||
var env = generators(); | ||
dependencies.forEach(function (d) { | ||
if (d instanceof Array) { | ||
env.register(d[0], d[1]); | ||
env.registerStub(d[0], d[1]); | ||
} else { | ||
@@ -216,3 +224,3 @@ env.register(d); | ||
var generator = env.create(name, {arguments: args}); | ||
var generator = env.create(name, {arguments: args, options: options}); | ||
@@ -219,0 +227,0 @@ generator.on('start', env.emit.bind(this, 'generators:start')); |
@@ -146,18 +146,20 @@ var logger = process.logging || require('./log'); | ||
var encoding = null; | ||
if (!isBinaryFile(path.resolve(filepath))) { | ||
encoding = 'utf8'; | ||
} | ||
if (!fs.statSync(path.resolve(filepath)).isDirectory()) { | ||
var encoding = null; | ||
if (!isBinaryFile(path.resolve(filepath))) { | ||
encoding = 'utf8'; | ||
} | ||
var actual = fs.readFileSync(path.resolve(filepath), encoding); | ||
var actual = fs.readFileSync(path.resolve(filepath), encoding); | ||
// In case of binary content, `actual` and `content` are `Buffer` objects, | ||
// we just can't compare those 2 objects with standard `===`, | ||
// so we convert each binary content to an hexadecimal string first, and then compare them with standard `===` | ||
// | ||
// For not binary content, we can directly compare the 2 strings this way | ||
if ((!encoding && (actual.toString('hex') === content.toString('hex'))) || | ||
(actual === content)) { | ||
log.identical(filepath); | ||
return cb('identical'); | ||
// In case of binary content, `actual` and `content` are `Buffer` objects, | ||
// we just can't compare those 2 objects with standard `===`, | ||
// so we convert each binary content to an hexadecimal string first, and then compare them with standard `===` | ||
// | ||
// For not binary content, we can directly compare the 2 strings this way | ||
if ((!encoding && (actual.toString('hex') === content.toString('hex'))) || | ||
(actual === content)) { | ||
log.identical(filepath); | ||
return cb('identical'); | ||
} | ||
} | ||
@@ -164,0 +166,0 @@ |
{ | ||
"name": "yeoman-generator", | ||
"version": "0.13.4", | ||
"version": "0.14.0-rc.1", | ||
"description": "Rails-inspired generator system that provides scaffolding for your apps", | ||
@@ -23,4 +23,4 @@ "keywords": [ | ||
"scripts": { | ||
"test": "DEBUG=generators:* mocha test/*.js --reporter list --timeout 100000", | ||
"legacy": "DEBUG=generators:* mocha test/legacy.js --reporter dot --timeout 100000", | ||
"test": "istanbul cover _mocha --report lcovonly -- test/*.js --reporter list --timeout 100000 && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage", | ||
"legacy": "mocha test/legacy.js --reporter dot --timeout 100000", | ||
"test-generator": "mocha test/generators/*.js --reporter spec --timeout 100000" | ||
@@ -30,9 +30,7 @@ }, | ||
"cheerio": "~0.12.0", | ||
"request": "~2.25.0", | ||
"rimraf": "~2.2.0", | ||
"tar": "~0.1.17", | ||
"diff": "~1.0.4", | ||
"mime": "~1.2.9", | ||
"underscore.string": "~2.3.1", | ||
"lodash": "~1.3.0", | ||
"lodash": "~2.2.1", | ||
"mkdirp": "~0.3.5", | ||
@@ -46,13 +44,17 @@ "glob": "~3.2.0", | ||
"iconv-lite": "~0.2.10", | ||
"shelljs": "~0.1.4", | ||
"shelljs": "~0.2.6", | ||
"findup-sync": "~0.1.2", | ||
"chalk": "~0.2.0", | ||
"text-table": "~0.1.1" | ||
"text-table": "~0.2.0", | ||
"download": "~0.1.6" | ||
}, | ||
"devDependencies": { | ||
"mocha": "~1.12.0", | ||
"proxyquire": "~0.4.0", | ||
"mocha": "~1.13.0", | ||
"proxyquire": "~0.5.1", | ||
"sinon": "~1.7.3", | ||
"markdox": "~0.1.2" | ||
"markdox": "~0.1.2", | ||
"coveralls": "~2.3.0", | ||
"mocha-lcov-reporter": "0.0.1", | ||
"istanbul": "~0.1.44" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
# Generator [![Build Status](https://secure.travis-ci.org/yeoman/generator.png?branch=master)](http://travis-ci.org/yeoman/generator) | ||
# Generator [![Build Status](https://secure.travis-ci.org/yeoman/generator.png?branch=master)](http://travis-ci.org/yeoman/generator) [![Coverage Status](https://coveralls.io/repos/yeoman/generator/badge.png)](https://coveralls.io/r/yeoman/generator) | ||
@@ -23,3 +23,24 @@ A Rails-inspired generator system that provides scaffolding for your apps. | ||
### Debugging | ||
To debug a generator, you can pass Node.js debug's flags by running it like this: | ||
```bash | ||
# OS X / Linux | ||
node --debug `which yo` <generator> [arguments] | ||
# Windows | ||
node --debug <path to yo binary> <generator> [arguments] | ||
``` | ||
Yeoman generators also use a debug mode to log relevant informations. You can activate it by setting the `DEBUG` environment variable to the desired scope (for the generator system scope is `generators:*`). | ||
```bash | ||
# OS X / Linux | ||
DEBUG=generators/* | ||
# Windows | ||
set DEBUG=generators/* | ||
``` | ||
## Officially maintained generators | ||
@@ -30,3 +51,2 @@ | ||
* [Backbone](https://github.com/yeoman/generator-backbone#readme) | ||
* [BBB (Backbone Boilerplate)](https://github.com/yeoman/generator-bbb#readme) | ||
* [Chrome Apps Basic Boilerplate](https://github.com/yeoman/generator-chromeapp#readme) | ||
@@ -33,0 +53,0 @@ * [Ember](https://github.com/yeoman/generator-ember#readme) |
@@ -9,2 +9,3 @@ /*global describe, before, it, afterEach, beforeEach */ | ||
var generators = require('../'); | ||
var helpers = generators.test; | ||
var EventEmitter = require('events').EventEmitter; | ||
@@ -18,14 +19,4 @@ var win32 = process.platform === 'win32'; | ||
before(function () { | ||
function Dummy() { | ||
generators.Base.apply(this, arguments); | ||
} | ||
util.inherits(Dummy, generators.Base); | ||
Dummy.prototype.test = function () { | ||
this.shouldRun = true; | ||
}; | ||
var env = this.env = generators(); | ||
env.register(Dummy, 'dummy'); | ||
env.registerStub(generators.test.createDummyGenerator(), 'dummy'); | ||
this.dummy = env.create('dummy'); | ||
@@ -126,19 +117,50 @@ | ||
it('should not give a conflict on same binary files', function (done) { | ||
this.dummy.conflicter.force = true; | ||
this.dummy.conflicter.collision('yeoman-logo.png', fs.readFileSync(path.join(this.fixtures, 'yeoman-logo.png')), function (status) { | ||
assert.equal(status, 'identical'); | ||
this.dummy.conflicter.force = false; | ||
done(); | ||
}.bind(this)); | ||
this.dummy.conflicter.force = true; | ||
this.dummy.conflicter.collision('yeoman-logo.png', fs.readFileSync(path.join(this.fixtures, 'yeoman-logo.png')), function (status) { | ||
assert.equal(status, 'identical'); | ||
this.dummy.conflicter.force = false; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
describe('generator.bulkCopy(source, destination, process)', function () { | ||
before(function (done) { | ||
this.dummy.bulkCopy(path.join(__dirname, 'fixtures/foo.js'), 'write/to/foo.js'); | ||
this.dummy.bulkCopy(path.join(__dirname, 'fixtures/foo-template.js'), 'write/to/noProcess.js'); | ||
done(); | ||
}); | ||
it('should copy a file', function (done) { | ||
fs.readFile('write/to/foo.js', function (err, data) { | ||
if (err) throw err; | ||
assert.equal(data+'', 'var foo = \'foo\';\n'); | ||
done(); | ||
}); | ||
}); | ||
it('should not run conflicter or template engine', function (done) { | ||
var self = this; | ||
fs.readFile('write/to/noProcess.js', function (err, data) { | ||
if (err) throw err; | ||
assert.equal(data+'', 'var <%= foo %> = \'<%= foo %>\';\n'); | ||
self.dummy.bulkCopy(path.join(__dirname, 'fixtures/foo.js'), 'write/to/noProcess.js'); | ||
fs.readFile('write/to/noProcess.js', function (err, data) { | ||
if (err) throw err; | ||
assert.equal(data+'', 'var foo = \'foo\';\n'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('generator.read(filepath, encoding)', function () { | ||
it('should read files relative to the "sourceRoot" value', function () { | ||
var body = this.dummy.read('foo.js'); | ||
assert.equal(body, 'var foo = \'foo\';' + '\n'); | ||
helpers.assertTextEqual(body, 'var foo = \'foo\';' + '\n'); | ||
}); | ||
it('should allow absolute path, and prevent the relative paths join', function () { | ||
var body = this.dummy.read(path.join(__dirname, 'fixtures/foo.js')); | ||
assert.equal(body, 'var foo = \'foo\';' + '\n'); | ||
helpers.assertTextEqual(body, 'var foo = \'foo\';' + '\n'); | ||
}); | ||
@@ -184,3 +206,3 @@ }); | ||
var body = fs.readFileSync('foo-template.js', 'utf8'); | ||
assert.equal(body, 'var fooooooo = \'fooooooo\';' + '\n'); | ||
helpers.assertTextEqual(body, 'var fooooooo = \'fooooooo\';' + '\n'); | ||
}); | ||
@@ -190,3 +212,3 @@ | ||
var body = fs.readFileSync('write/to/from-template-bar.js', 'utf8'); | ||
assert.equal(body, 'var bar = \'bar\';' + '\n'); | ||
helpers.assertTextEqual(body, 'var bar = \'bar\';' + '\n'); | ||
}); | ||
@@ -196,3 +218,3 @@ | ||
var body = fs.readFileSync('write/to/from-template.js', 'utf8'); | ||
assert.equal(body, 'var fooooooo = \'fooooooo\';' + '\n'); | ||
helpers.assertTextEqual(body, 'var fooooooo = \'fooooooo\';' + '\n'); | ||
}); | ||
@@ -252,3 +274,3 @@ }); | ||
var foo = this.dummy.foo; | ||
assert.equal(body, 'var ' + foo + ' = \'' + foo + '\';\n'); | ||
helpers.assertTextEqual(body, 'var ' + foo + ' = \'' + foo + '\';\n'); | ||
}); | ||
@@ -258,6 +280,45 @@ | ||
var body = fs.readFileSync('directory-processed/foo-process.js', 'utf8'); | ||
assert.equal(body, 'var bar = \'foo\';\n'); | ||
helpers.assertTextEqual(body, 'var bar = \'foo\';\n'); | ||
}); | ||
}); | ||
describe('generator.bulkDirectory(source, destination, process)', function () { | ||
before(function (done) { | ||
this.dummy.sourceRoot(this.fixtures); | ||
this.dummy.destinationRoot('.'); | ||
// Create temp bulk operation files | ||
// These cannot just be in the repo or the other directory tests fail | ||
require('mkdirp').sync(this.fixtures + '/bulk-operation'); | ||
for (var i = 0; i < 1000; i++) { | ||
fs.writeFileSync(this.fixtures + '/bulk-operation/' + i + '.js', i); | ||
} | ||
// Copy files without processing | ||
this.dummy.bulkDirectory('bulk-operation', 'bulk-operation'); | ||
this.dummy.conflicter.resolve(done); | ||
}); | ||
after(function (done) { | ||
// Now remove them | ||
for (var i = 0; i < 1000; i++) { | ||
fs.unlinkSync(this.fixtures + '/bulk-operation/' + i + '.js'); | ||
} | ||
fs.rmdirSync(this.fixtures + '/bulk-operation'); | ||
done(); | ||
}); | ||
it('should bulk copy one thousand files', function (done) { | ||
fs.readFile('bulk-operation/999.js', function (err, data) { | ||
if (err) throw err; | ||
assert.equal(data, '999'); | ||
done(); | ||
}); | ||
}); | ||
it('should check for conflict if directory already exists', function (done) { | ||
this.dummy.bulkDirectory('bulk-operation', 'bulk-operation'); | ||
this.dummy.conflicter.resolve(done); | ||
}); | ||
}); | ||
describe('actions/install', function () { | ||
@@ -264,0 +325,0 @@ var asyncStub = { |
@@ -21,17 +21,9 @@ /*global describe, before, beforeEach, after, afterEach, it */ | ||
function Dummy() { | ||
generators.Base.apply(this, arguments); | ||
} | ||
var Dummy = generators.test.createDummyGenerator(); | ||
util.inherits(Dummy, generators.Base); | ||
Dummy.prototype.test = function () { | ||
this.shouldRun = true; | ||
}; | ||
env.register(Dummy, 'ember:all'); | ||
env.register(Dummy, 'hook1:ember'); | ||
env.register(Dummy, 'hook2:ember:all'); | ||
env.register(Dummy, 'hook3'); | ||
env.register(function () { | ||
env.registerStub(Dummy, 'ember:all'); | ||
env.registerStub(Dummy, 'hook1:ember'); | ||
env.registerStub(Dummy, 'hook2:ember:all'); | ||
env.registerStub(Dummy, 'hook3'); | ||
env.registerStub(function () { | ||
this.write('app/scripts/models/application-model.js', '// ...'); | ||
@@ -261,3 +253,3 @@ }, 'hook4'); | ||
assert.ok(help.match('Usage:')); | ||
assert.ok(help.match('yeoman init FOO one two three \\[options\\]')); | ||
assert.ok(help.match('yo \\[options\\]')); | ||
assert.ok(help.match('A new desc for this generator')); | ||
@@ -273,4 +265,9 @@ assert.ok(help.match('Options:')); | ||
var usage = this.dummy.usage(); | ||
assert.equal(usage, 'yeoman init FOO one two three [options]\n\nA new desc for this generator'); | ||
assert.equal(usage, 'yo [options]\n\nA new desc for this generator'); | ||
}); | ||
it('should use the provided generatorName', function() { | ||
this.dummy.generatorName = 'dummy'; | ||
assert.ok(this.dummy.usage().match('yo dummy')); | ||
}); | ||
}); | ||
@@ -277,0 +274,0 @@ |
@@ -80,4 +80,19 @@ /*global it, describe, before */ | ||
assert.ok(extend.namespace, 'scaffold'); | ||
// should only accept String as first parameter | ||
assert.throws(function () { env.register(function () {}, 'blop'); }); | ||
assert.throws(function () { env.register([], 'blop'); }); | ||
assert.throws(function () { env.register(false, 'blop'); }); | ||
}); | ||
// Make sure we don't break the generators hash using `Object.defineProperty` | ||
it('should keep internal generators object writable', function () { | ||
var env = generators(); | ||
env.register('../fixtures/custom-generator-simple', 'foo'); | ||
env.generators.foo = 'bar'; | ||
assert.equal(env.generators.foo, 'bar'); | ||
env.generators.foo = 'yo'; | ||
assert.equal(env.generators.foo, 'yo'); | ||
}); | ||
it('get the list of namespaces', function () { | ||
@@ -101,6 +116,6 @@ var namespaces = generators() | ||
// fs.writeFileSync(path.join(__dirname, 'fixtures/help.txt'), env.help().trim()); | ||
assert.equal(env.help().trim(), expected.trim()); | ||
helpers.assertTextEqual(env.help().trim(), expected.trim()); | ||
// custom bin name | ||
assert.equal(env.help('gg').trim(), expected.replace('Usage: init', 'Usage: gg').trim()); | ||
helpers.assertTextEqual(env.help('gg').trim(), expected.replace('Usage: init', 'Usage: gg').trim()); | ||
}); | ||
@@ -180,3 +195,3 @@ | ||
assert.equal(fs.readFileSync(filename, 'utf8'), "var hey = 'hey';" + '\n'); | ||
helpers.assertTextEqual(fs.readFileSync(filename, 'utf8'), "var hey = 'hey';" + '\n'); | ||
done(); | ||
@@ -269,3 +284,3 @@ }); | ||
generators() | ||
.register(this.Generator) | ||
.registerStub(this.Generator, 'angular:all') | ||
// Series of events proxied from the resolved generator | ||
@@ -272,0 +287,0 @@ .on('generators:start', assertEvent('generators:start')) |
@@ -11,3 +11,3 @@ /*global describe, before, it */ | ||
before(function () { | ||
this.env = generators().register(function () {}, 'ember:model'); | ||
this.env = generators().registerStub(function () {}, 'ember:model'); | ||
}); | ||
@@ -14,0 +14,0 @@ |
@@ -44,7 +44,7 @@ /*global describe, before, it */ | ||
it('should allow the fecthing / untar of a given tarball, at the given location', function (done) { | ||
this.dummy.tarball('https://github.com/yeoman/yeoman.io/tarball/gh-pages', './yeoman.io/', function (err) { | ||
this.dummy.tarball('https://github.com/yeoman/generator/archive/master.tar.gz', './yeoman-generator/', function (err) { | ||
if (err) { | ||
return done(err); | ||
} | ||
fs.stat('./yeoman.io/index.html', done); | ||
fs.stat('./yeoman-generator/readme.md', done); | ||
}); | ||
@@ -56,3 +56,3 @@ }); | ||
it('should allow the fething of a single file', function (done) { | ||
this.dummy.fetch('https://raw.github.com/yeoman/generators/master/README.md', './some/path/README.md', function (err) { | ||
this.dummy.fetch('https://raw.github.com/yeoman/generator/master/readme.md', './some/path/README.md', function (err) { | ||
if (err) { | ||
@@ -59,0 +59,0 @@ return done(err); |
@@ -15,6 +15,10 @@ | ||
// in several methods. | ||
var util = require('util'); | ||
var generators = require('../../../main'); | ||
module.exports = function(args, options) { | ||
generators.Base.apply(this, arguments); | ||
console.log('Executing generator with', args, options); | ||
}; | ||
util.inherits(module.exports, generators.Base); | ||
@@ -21,0 +25,0 @@ module.exports.name = 'You can name your generator'; |
@@ -61,2 +61,60 @@ /*global describe, before, it */ | ||
}); | ||
it('should append content in the right place', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body><section><span></span>TEST</section></body></html>'; | ||
assert.equal(wiring.append(html, 'section', 'TEST'), expected); | ||
assert.equal(wiring.domUpdate(html, 'section', 'TEST', 'a'), expected); | ||
}); | ||
it('should prepend content in the right place', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body><section>TEST<span></span></section></body></html>'; | ||
assert.equal(wiring.prepend(html, 'section', 'TEST'), expected); | ||
assert.equal(wiring.domUpdate(html, 'section', 'TEST', 'p'), expected); | ||
}); | ||
it('should replace content correctly', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body><section>TEST</section></body></html>'; | ||
assert.equal(wiring.domUpdate(html, 'section', 'TEST', 'r'), expected); | ||
}); | ||
it('should delete content correctly', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body></body></html>'; | ||
assert.equal(wiring.domUpdate(html, 'section', 'TEST', 'd'), expected); | ||
}); | ||
it('should append to files in the right place', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body><section><span></span>TEST</section></body></html>'; | ||
var filepath = path.join(this.fixtures, 'append-prepend-to-file.html'); | ||
fs.writeFileSync(filepath, html, 'utf-8'); | ||
wiring.appendToFile(filepath, 'section', 'TEST'); | ||
var actual = fs.readFileSync(filepath, 'utf-8').trim(); | ||
assert.equal(actual, expected); | ||
fs.writeFileSync(filepath, html, 'utf-8'); | ||
}); | ||
it('should prepend to files in the right place', function () { | ||
var html = '<html><body><section><span></span></section></body></html>'; | ||
var expected = '<html><body><section>TEST<span></span></section></body></html>'; | ||
var filepath = path.join(this.fixtures, 'append-prepend-to-file.html'); | ||
fs.writeFileSync(filepath, html, 'utf-8'); | ||
wiring.prependToFile(filepath, 'section', 'TEST'); | ||
var actual = fs.readFileSync(filepath, 'utf-8').trim(); | ||
assert.equal(actual, expected); | ||
fs.writeFileSync(filepath, html, 'utf-8'); | ||
}); | ||
}); |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
498458
19
73
8743
55
8
7
+ Addeddownload@~0.1.6
+ Addedabbrev@1.1.1(transitive)
+ Addedadm-zip@0.4.16(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddecompress@0.2.5(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addeddownload@0.1.19(transitive)
+ Addedduplexer@0.1.2(transitive)
+ Addedeach-async@0.1.3(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedext-list@0.2.0(transitive)
+ Addedext-name@1.0.1(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedget-stdin@0.1.0(transitive)
+ Addedget-urls@0.1.2(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedgot@0.2.0(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedlodash@2.2.1(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addednopt@2.2.1(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedobject-assign@0.3.1(transitive)
+ Addedobject-keys@0.4.0(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedshelljs@0.2.6(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedstream-combiner@0.0.4(transitive)
+ Addedtempfile@0.1.3(transitive)
+ Addedtext-table@0.2.0(transitive)
+ Addedthrough2@0.4.2(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addeduuid@1.4.23.4.0(transitive)
+ Addedverror@1.10.0(transitive)
+ Addedxtend@2.1.2(transitive)
- Removedrequest@~2.25.0
- Removedtar@~0.1.17
- Removedasn1@0.1.11(transitive)
- Removedassert-plus@0.1.5(transitive)
- Removedasync@0.9.2(transitive)
- Removedaws-sign@0.3.0(transitive)
- Removedboom@0.4.2(transitive)
- Removedcombined-stream@0.0.7(transitive)
- Removedcookie-jar@0.3.0(transitive)
- Removedcryptiles@0.2.2(transitive)
- Removedctype@0.5.3(transitive)
- Removeddelayed-stream@0.0.5(transitive)
- Removedforever-agent@0.5.2(transitive)
- Removedform-data@0.1.4(transitive)
- Removedhawk@1.0.0(transitive)
- Removedhoek@0.9.1(transitive)
- Removedhttp-signature@0.10.1(transitive)
- Removedlodash@1.3.1(transitive)
- Removednode-uuid@1.4.8(transitive)
- Removedoauth-sign@0.3.0(transitive)
- Removedqs@0.6.6(transitive)
- Removedrequest@2.25.0(transitive)
- Removedshelljs@0.1.4(transitive)
- Removedsntp@0.2.4(transitive)
- Removedtext-table@0.1.1(transitive)
- Removedtunnel-agent@0.3.0(transitive)
Updatedlodash@~2.2.1
Updatedshelljs@~0.2.6
Updatedtext-table@~0.2.0