Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

grunt

Package Overview
Dependencies
Maintainers
2
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt - npm Package Compare versions

Comparing version 0.4.0-rc4 to 0.4.0-rc5

test/grunt/option_test.js

29

Gruntfile.js

@@ -20,11 +20,5 @@ /*

jshint: {
all: [
'Gruntfile.js',
'lib/**/*.js',
'tasks/*.js',
'tasks/*/*.js',
'tasks/lib/**/*.js',
'<%= nodeunit.all %>',
'test/gruntfile/*.js',
],
gruntfile: ['Gruntfile.js'],
libs_n_tests: ['lib/**/*.js', '<%= nodeunit.all %>'],
subgrunt: ['<%= subgrunt.all %>'],
options: {

@@ -47,5 +41,13 @@ curly: true,

watch: {
scripts: {
files: ['<%= jshint.all %>'],
tasks: ['test']
gruntfile: {
files: ['<%= jshint.gruntfile %>'],
tasks: ['jshint:gruntfile']
},
libs_n_tests: {
files: ['<%= jshint.libs_n_tests %>'],
tasks: ['jshint:libs_n_tests', 'nodeunit']
},
subgrunt: {
files: ['<%= subgrunt.all %>'],
tasks: ['jshint:subgrunt', 'subgrunt']
}

@@ -72,4 +74,3 @@ },

var path = require('path');
var files = grunt.file.expandFiles(this.file.src);
grunt.util.async.forEachSeries(files, function(gruntfile, next) {
grunt.util.async.forEachSeries(this.filesSrc, function(gruntfile, next) {
grunt.util.spawn({

@@ -76,0 +77,0 @@ grunt: true,

@@ -55,3 +55,9 @@ /*

config.get = function(prop) {
return grunt.util.recurse(config.getRaw(prop), function(value) {
return config.process(config.getRaw(prop));
};
// Expand a config value recursively. Used for post-processing raw values
// already retrieved from the config.
config.process = function(raw) {
return grunt.util.recurse(raw, function(value) {
// If the value is not a string, return it.

@@ -58,0 +64,0 @@ if (typeof value !== 'string') { return value; }

@@ -42,5 +42,17 @@ /*

// If --stack is enabled, log the appropriate error stack (if it exists).
function dumpStack(e) {
if (grunt.option('stack')) {
if (e.origError && e.origError.stack) {
console.log(e.origError.stack);
} else if (e.stack) {
console.log(e.stack);
}
}
}
// A fatal error occured. Abort immediately.
fail.fatal = function(e, errcode) {
writeln(e, 'fatal');
dumpStack(e);
process.exit(typeof errcode === 'number' ? errcode : fail.code.GENERAL_ERROR);

@@ -60,11 +72,3 @@ };

if (!grunt.option('force')) {
// If --stack is enabled, log the appropriate error stack (if it exists).
if (grunt.option('stack')) {
if (e.origError && e.origError.stack) {
console.log(e.origError.stack);
} else if (e.stack) {
console.log(e.stack);
}
}
// Log and exit.
dumpStack(e);
grunt.log.writeln().fail('Aborted due to warnings.');

@@ -71,0 +75,0 @@ process.exit(typeof errcode === 'number' ? errcode : fail.code.WARNING);

@@ -110,58 +110,26 @@ /*

// Return all matching filepaths.
return processPatterns(patterns, function(pattern) {
var matches = processPatterns(patterns, function(pattern) {
// Find all matching files for this pattern.
return file.glob.sync(pattern, options);
});
// Filter result set?
if (options.filter) {
matches = matches.filter(function(filepath) {
filepath = path.join(options.cwd, filepath);
try {
if (typeof options.filter === 'function') {
return options.filter(filepath);
} else {
// If the file is of the right type and exists, this should work.
return fs.statSync(filepath)[options.filter]();
}
} catch(e) {
// Otherwise, it's probably not the right type.
return false;
}
});
}
return matches;
};
// Further filter file.expand.
var expandByType = function(type) {
var args = grunt.util.toArray(arguments).slice(1);
// If the first argument is an options object, grab it.
var options = grunt.util.kindOf(args[0]) === 'object' ? args[0] : {};
// Match, then filter filepaths.
return file.expand.apply(file, args).filter(function(filepath) {
try {
// If the file is of the right type and exists, this should work.
return fs.statSync(path.join(options.cwd, filepath))[type]();
} catch(e) {
// Otherwise, it's probably not the right type.
return false;
}
});
};
// A few type-specific file expansion methods.
file.expandDirs = expandByType.bind(file, 'isDirectory');
file.expandFiles = expandByType.bind(file, 'isFile');
// Return an array of all file paths that match the given wildcard patterns,
// plus a uniqed list of any URLs that were passed, at the end.
file.expandFileURLs = function() {
// Use the first argument if it's an Array, otherwise convert the arguments
// object to an array and use that.
var patterns = Array.isArray(arguments[0]) ? arguments[0] : grunt.util.toArray(arguments);
var urls = [];
// Filter all URLs out of patterns list and store them in a separate array.
patterns = grunt.util._.flatten(patterns).filter(function(pattern) {
if (/^(?:file|https?):\/\//i.test(pattern)) {
// Push onto urls array.
urls.push(pattern);
// Remove from patterns array.
return false;
}
// Otherwise, keep pattern.
return true;
});
// Return uniqed array of expanded filepaths with urls at end.
return grunt.util._.uniq(file.expandFiles(patterns).map(function(filepath) {
var abspath = path.resolve(filepath);
// Convert C:\foo\bar style paths to /C:/foo/bar.
if (abspath.indexOf('/') !== 0) {
abspath = unixifyPath('/' + abspath);
}
return 'file://' + abspath;
}).concat(urls));
};
var pathSeparatorRe = /[\/\\]/g;

@@ -176,7 +144,14 @@

});
var files = {};
var files = [];
// Find all files matching pattern, using passed-in options.
file.expand(options, patterns).forEach(function(src) {
// Flatten if specified.
var destPath = options.flatten ? path.basename(src) : src;
var destPath = src;
// Flatten?
if (options.flatten) {
destPath = path.basename(destPath);
}
// Change the extension?
if (options.ext) {
destPath = destPath.replace(/(\..*)?$/, options.ext);
}
// Generate destination filename.

@@ -190,3 +165,6 @@ var dest = options.rename(destBase, destPath, options);

// Map correct src path to dest path.
files[dest] = src;
files.push({
src: src,
dest: dest,
});
});

@@ -193,0 +171,0 @@ return files;

@@ -52,2 +52,3 @@ /*

Object.defineProperty(this, 'errorCount', {
enumerable: true,
get: function() {

@@ -103,3 +104,3 @@ return grunt.fail.errorcount - errorcount;

for (prop in data.files) {
files.push({src: data.files[prop], dest: prop});
files.push({src: data.files[prop], dest: grunt.config.process(prop)});
}

@@ -113,3 +114,3 @@ } else if (Array.isArray(data.files)) {

for (prop in obj) {
files.push({src: obj[prop], dest: prop});
files.push({src: obj[prop], dest: grunt.config.process(prop)});
}

@@ -120,29 +121,61 @@ }

} else {
files.push({src: Array.isArray(data) ? data : [data], dest: target});
files.push({src: data, dest: grunt.config.process(target)});
}
// If no files were specified, a single empty files object should be
// returned so that the task function will still actually run.
// If no src/dest or files were specified, return an empty files array.
if (files.length === 0) {
return [{}];
grunt.verbose.writeln('File: ' + '[no files]'.red);
return [];
}
// Process each normalized file object as a template.
files.forEach(function(obj) {
if ('src' in obj) {
// Expose the un-expanded (but normalized) src list as .srcRaw.
obj.srcRaw = obj.src;
// Process obj.srcRaw as a template (recursively, if necessary).
obj.srcRaw = grunt.util.recurse(obj.srcRaw, function(src) {
if (typeof src !== 'string') { return src; }
return grunt.template.process(src);
// Process all normalized file objects.
files = grunt.util._(files).chain().forEach(function(obj) {
if (!('src' in obj) || !obj.src) { return; }
// Normalize .src properties to flattened array.
if (Array.isArray(obj.src)) {
obj.src = grunt.util._.flatten(obj.src);
} else {
obj.src = [obj.src];
}
}).map(function(obj) {
// Build options object, removing unwanted properties.
var expandOptions = grunt.util._.extend({}, obj);
delete expandOptions.src;
delete expandOptions.dest;
// Expand file mappings.
if (obj.expand) {
return grunt.file.expandMapping(obj.src, obj.dest, expandOptions).map(function(mapObj) {
// Copy obj properties to result.
var result = grunt.util._.extend({}, obj);
// Make a clone of the orig obj available.
result.orig = grunt.util._.extend({}, obj);
// Set .src and .dest, processing both as templates.
result.src = [grunt.config.process(mapObj.src)];
result.dest = grunt.config.process(mapObj.dest);
// Remove unwanted properties.
['expand', 'cwd', 'flatten', 'rename', 'ext'].forEach(function(prop) {
delete result[prop];
});
return result;
});
// If obj.srcRaw is an array, flatten it. Otherwise, make it into an array.
obj.srcRaw = Array.isArray(obj.srcRaw) ? grunt.util._.flatten(obj.srcRaw) : [obj.srcRaw];
}
// Copy obj properties to result, adding an .orig property.
var result = grunt.util._.extend({}, obj);
// Make a clone of the orig obj available.
result.orig = grunt.util._.extend({}, obj);
if ('src' in result) {
// Expose an expand-on-demand getter method as .src.
Object.defineProperty(obj, 'src', {
Object.defineProperty(result, 'src', {
enumerable: true,
get: function fn() {
var src;
if (!('result' in fn)) {
fn.result = grunt.file.expand(obj.srcRaw);
src = obj.src;
// If src is an array, flatten it. Otherwise, make it into an array.
src = Array.isArray(src) ? grunt.util._.flatten(src) : [src];
// Expand src files, memoizing result.
fn.result = grunt.file.expand(expandOptions, src);
}

@@ -154,8 +187,25 @@ return fn.result;

if ('dest' in obj) {
// Process dest as a template.
obj.dest = grunt.template.process(obj.dest);
if ('dest' in result) {
result.dest = obj.dest;
}
});
return result;
}).flatten().value();
// Log this.file src and dest properties when --verbose is specified.
if (grunt.option('verbose')) {
files.forEach(function(obj) {
var output = [];
if ('src' in obj) {
output.push(obj.src.length > 0 ? grunt.log.wordlist(obj.src) : '[no src]'.red);
}
if ('dest' in obj) {
output.push('-> ' + (obj.dest ? String(obj.dest).cyan : '[no dest]'.red));
}
if (output.length > 0) {
grunt.verbose.writeln('Files: ' + output.join(' '));
}
});
}
return files;

@@ -177,6 +227,6 @@ };

// Arguments (sans target) as an array.
var args = grunt.util.toArray(arguments).slice(1);
this.args = grunt.util.toArray(arguments).slice(1);
// If a target wasn't specified, run this task once for each target.
if (!target || target === '*') {
return task.runAllTargets(name, args);
return task.runAllTargets(name, this.args);
} else if (!isValidMultiTaskTarget(target)) {

@@ -187,52 +237,30 @@ throw new Error('Invalid target "' + target + '" specified.');

this.requiresConfig([name, target]);
// Target data.
var data = grunt.config([name, target]);
// Initialize the errorcount for this task.
errorcount = grunt.fail.errorcount;
// Normalize files object.
var files = task.normalizeMultiTaskFiles(data, target);
// For each file object, call original task function, passing in the
// target and any other args.
grunt.util.async.forEachSeries(files, function(fileObj, next) {
var context = {};
// Copy some properties over from the main task `this` object.
[
'nameArgs',
'name',
'args',
'flags',
'requiresConfig',
'requires',
].forEach(function(key) {
context[key] = this[key];
}, this);
// Return the number of errors logged during this task.
Object.defineProperty(context, 'errorCount', {
get: function() {
return grunt.fail.errorcount - errorcount;
}
});
// Return an options object with the specified defaults overriden by task-
// and/or target-specific overrides, via the "options" property.
context.options = function() {
var targetObj = grunt.config([name, target]);
var args = [{}].concat(grunt.util.toArray(arguments)).concat([
grunt.config([name, 'options']),
grunt.util.kindOf(targetObj) === 'object' ? targetObj.options : {}
]);
return grunt.util._.extend.apply(null, args);
};
// Expose data on `context` (as well as task.current).
context.data = data;
// Expose the current target.
context.target = target;
// Expose file object.
context.file = fileObj;
// Actually run the task function (handling this.async, etc)
task.runTaskFn(context, function() {
return fn.apply(this, this.args);
}, next);
}.bind(this), this.async());
// Return an options object with the specified defaults overriden by task-
// and/or target-specific overrides, via the "options" property.
this.options = function() {
var targetObj = grunt.config([name, target]);
var args = [{}].concat(grunt.util.toArray(arguments)).concat([
grunt.config([name, 'options']),
grunt.util.kindOf(targetObj) === 'object' ? targetObj.options : {}
]);
return grunt.util._.extend.apply(null, args);
};
// Expose data on `this` (as well as task.current).
this.data = grunt.config([name, target]);
// Expose normalized files object.
this.files = task.normalizeMultiTaskFiles(this.data, target);
// Expose normalized, flattened, uniqued array of src files.
Object.defineProperty(this, 'filesSrc', {
enumerable: true,
get: function() {
return grunt.util._(this.files).chain().pluck('src').flatten().uniq().value();
}.bind(this)
});
// Expose the current target.
this.target = target;
// Recreate flags object so that the target isn't set as a flag.
this.flags = {};
this.args.forEach(function(arg) { this.flags[arg] = true; }, this);
// Call original task function, passing in the target and any other args.
return fn.apply(this, this.args);
});

@@ -263,3 +291,3 @@

// Get an array of sub-property keys under the given config object.
var targets = Object.keys(grunt.config(taskname) || {});
var targets = Object.keys(grunt.config.getRaw(taskname) || {});
// Fail if there are no actual properties to iterate over.

@@ -354,3 +382,3 @@ if (targets.length === 0) {

// Process collection plugins.
if (pkg.keywords.indexOf('gruntcollection') !== -1) {
if (pkg.keywords && pkg.keywords.indexOf('gruntcollection') !== -1) {
loadTaskDepth++;

@@ -397,3 +425,3 @@ Object.keys(pkg.dependencies).forEach(function(depName) {

var msg = 'Reading "' + path.basename(gruntfile) + '" Gruntfile...';
var msg = 'Reading "' + (gruntfile ? path.basename(gruntfile) : '???') + '" Gruntfile...';
if (gruntfile && grunt.file.exists(gruntfile)) {

@@ -415,8 +443,8 @@ grunt.verbose.writeln().write(msg).ok();

grunt.verbose.writeln().write(msg).error();
if (grunt.file.findup(process.cwd(), 'grunt.js')) {
grunt.log.errorlns('The Gruntfile name has changed to "Gruntfile.js", ' +
'but a "grunt.js" file was found. If this is your project\'s ' +
'Gruntfile, please rename it. (grunt 0.4.0+)');
}
grunt.fatal('Unable to find Gruntfile. Do you need any --help?', grunt.fail.code.MISSING_GRUNTFILE);
grunt.log.writelns(
'A valid Gruntfile could not be found. Please see the getting ' +
'started guide for more information on how to configure grunt: ' +
'http://gruntjs.com/getting-started'
);
grunt.fatal('Unable to find Gruntfile.', grunt.fail.code.MISSING_GRUNTFILE);
}

@@ -423,0 +451,0 @@

{
"name": "grunt",
"description": "A task-based command line build tool for JavaScript projects.",
"version": "0.4.0rc4",
"version": "0.4.0rc5",
"author": "\"Cowboy\" Ben Alman (http://benalman.com/)",

@@ -65,6 +65,7 @@ "homepage": "http://gruntjs.com/",

"temporary": "~0.0.4",
"grunt-contrib-jshint": "~0.1.0",
"grunt-contrib-nodeunit": "~0.1.0",
"grunt-contrib-watch": "~0.1.4"
"grunt-contrib-jshint": "~0.1.1rc5",
"grunt-contrib-nodeunit": "~0.1.2rc5",
"grunt-contrib-watch": "~0.2.0a",
"difflet": "~0.2.3"
}
}

@@ -50,2 +50,11 @@ 'use strict';

},
'config.process': function(test) {
test.expect(5);
test.equal(grunt.config.process('<%= meta.foo %>'), 'bar', 'Should process templates.');
test.equal(grunt.config.process('<%= foo %>'), 'bar', 'Should process templates recursively.');
test.equal(grunt.config.process('<%= obj.foo %>'), 'bar', 'Should process deeply nested templates recursively.');
test.deepEqual(grunt.config.process(['foo', '<%= obj.foo2 %>']), ['foo', 'bar'], 'Should process templates in arrays.');
test.deepEqual(grunt.config.process(['<%= arr %>', '<%= obj.Arr %>']), [['foo', 'bar'], ['foo', 'bar']], 'Should expand <%= arr %> and <%= obj.Arr %> values as objects if possible.');
test.done();
},
'config.get': function(test) {

@@ -52,0 +61,0 @@ test.expect(8);

@@ -117,3 +117,3 @@ 'use strict';

'basic matching': function(test) {
test.expect(9);
test.expect(8);
test.deepEqual(grunt.file.expand('**/*.js'), ['js/bar.js', 'js/foo.js'], 'should match.');

@@ -136,6 +136,2 @@ test.deepEqual(grunt.file.expand('**/*.js', '**/*.css'), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');

'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.');
test.deepEqual(grunt.file.expandFiles('**d*/**'), [
'deep/deep.txt',
'deep/deeper/deeper.txt',
'deep/deeper/deepest/deepest.txt'], 'should match files only.');
test.deepEqual(grunt.file.expand('**d*/**/'), [

@@ -145,3 +141,2 @@ 'deep/',

'deep/deeper/deepest/'], 'should match directories, arbitrary / at the end appears in matches.');
// test.ok(true);
test.deepEqual(grunt.file.expand({mark: true}, '**d*/**/'), [

@@ -151,15 +146,25 @@ 'deep/',

'deep/deeper/deepest/'], 'should match directories, arbitrary / at the end appears in matches.');
test.deepEqual(grunt.file.expandDirs('**d*/**'), [
test.deepEqual(grunt.file.expand('*.xyz'), [], 'should fail to match.');
test.done();
},
'filter': function(test) {
test.expect(5);
test.deepEqual(grunt.file.expand({filter: 'isFile'}, '**d*/**'), [
'deep/deep.txt',
'deep/deeper/deeper.txt',
'deep/deeper/deepest/deepest.txt'
], 'should match files only.');
test.deepEqual(grunt.file.expand({filter: 'isDirectory'}, '**d*/**'), [
'deep',
'deep/deeper',
'deep/deeper/deepest'], 'should match directories only.');
'deep/deeper/deepest'
], 'should match directories only.');
test.deepEqual(grunt.file.expand({filter: function(filepath) { return (/deepest/).test(filepath); }}, '**'), [
'deep/deeper/deepest',
'deep/deeper/deepest/deepest.txt',
], 'should filter arbitrarily.');
test.deepEqual(grunt.file.expand({filter: 'isFile'}, 'js', 'css'), [], 'should fail to match.');
test.deepEqual(grunt.file.expand({filter: 'isDirectory'}, '**/*.js'), [], 'should fail to match.');
test.done();
},
'no matches': function(test) {
test.expect(3);
test.deepEqual(grunt.file.expand('*.xyz'), [], 'should fail to match.');
test.deepEqual(grunt.file.expandDirs('**/*.js'), [], 'should fail to match.');
test.deepEqual(grunt.file.expandFiles('js', 'css'), [], 'should fail to match.');
test.done();
},
'unique': function(test) {

@@ -220,7 +225,7 @@ test.expect(4);

test.expect(4);
var opts = {cwd: path.resolve(process.cwd(), '..')};
test.deepEqual(grunt.file.expand(opts, ['expand/js', 'expand/js/*']), ['expand/js', 'expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
test.deepEqual(grunt.file.expandFiles(opts, ['expand/js', 'expand/js/*']), ['expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
test.deepEqual(grunt.file.expandDirs(opts, ['expand/js', 'expand/js/*']), ['expand/js'], 'should match.');
test.deepEqual(grunt.file.expandFiles(opts, ['expand/js', 'expand/js/*', '!**/b*.js']), ['expand/js/foo.js'], 'should negate properly.');
var cwd = path.resolve(process.cwd(), '..');
test.deepEqual(grunt.file.expand({cwd: cwd}, ['expand/js', 'expand/js/*']), ['expand/js', 'expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*']), ['expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isDirectory'}, ['expand/js', 'expand/js/*']), ['expand/js'], 'should match.');
test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*', '!**/b*.js']), ['expand/js/foo.js'], 'should negate properly.');
test.done();

@@ -251,7 +256,7 @@ },

var actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest');
var expected = {
'dest/expand/deep/deep.txt': 'expand/deep/deep.txt',
'dest/expand/deep/deeper/deeper.txt': 'expand/deep/deeper/deeper.txt',
'dest/expand/deep/deeper/deepest/deepest.txt': 'expand/deep/deeper/deepest/deepest.txt',
};
var expected = [
{dest: 'dest/expand/deep/deep.txt', src: 'expand/deep/deep.txt'},
{dest: 'dest/expand/deep/deeper/deeper.txt', src: 'expand/deep/deeper/deeper.txt'},
{dest: 'dest/expand/deep/deeper/deepest/deepest.txt', src: 'expand/deep/deeper/deepest/deepest.txt'},
];
test.deepEqual(actual, expected, 'basic src-dest options');

@@ -267,18 +272,29 @@

var actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {flatten: true});
var expected = {
'dest/deep.txt': 'expand/deep/deep.txt',
'dest/deeper.txt': 'expand/deep/deeper/deeper.txt',
'dest/deepest.txt': 'expand/deep/deeper/deepest/deepest.txt',
};
var expected = [
{dest: 'dest/deep.txt', src: 'expand/deep/deep.txt'},
{dest: 'dest/deeper.txt', src: 'expand/deep/deeper/deeper.txt'},
{dest: 'dest/deepest.txt', src: 'expand/deep/deeper/deepest/deepest.txt'},
];
test.deepEqual(actual, expected, 'dest paths should be flattened pre-destBase+destPath join');
test.done();
},
'ext': function(test) {
test.expect(1);
var actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {ext: '.foo'});
var expected = [
{dest: 'dest/expand/deep/deep.foo', src: 'expand/deep/deep.txt'},
{dest: 'dest/expand/deep/deeper/deeper.foo', src: 'expand/deep/deeper/deeper.txt'},
{dest: 'dest/expand/deep/deeper/deepest/deepest.foo', src: 'expand/deep/deeper/deepest/deepest.txt'},
];
test.deepEqual(actual, expected, 'specified extension should be added');
test.done();
},
'cwd': function(test) {
test.expect(1);
var actual = grunt.file.expandMapping(['**/*.txt'], 'dest', {cwd: 'expand'});
var expected = {
'dest/deep/deep.txt': 'expand/deep/deep.txt',
'dest/deep/deeper/deeper.txt': 'expand/deep/deeper/deeper.txt',
'dest/deep/deeper/deepest/deepest.txt': 'expand/deep/deeper/deepest/deepest.txt',
};
var expected = [
{dest: 'dest/deep/deep.txt', src: 'expand/deep/deep.txt'},
{dest: 'dest/deep/deeper/deeper.txt', src: 'expand/deep/deeper/deeper.txt'},
{dest: 'dest/deep/deeper/deepest/deepest.txt', src: 'expand/deep/deeper/deepest/deepest.txt'},
];
test.deepEqual(actual, expected, 'cwd should be stripped from front of destPath, pre-destBase+destPath join');

@@ -296,7 +312,7 @@ test.done();

});
var expected = {
'dest/expand/o-m-g/deep.txt': 'expand/deep/deep.txt',
'dest/expand/o-m-g/deeper.txt': 'expand/deep/deeper/deeper.txt',
'dest/expand/o-m-g/deepest.txt': 'expand/deep/deeper/deepest/deepest.txt',
};
var expected = [
{dest: 'dest/expand/o-m-g/deep.txt', src: 'expand/deep/deep.txt'},
{dest: 'dest/expand/o-m-g/deeper.txt', src: 'expand/deep/deeper/deeper.txt'},
{dest: 'dest/expand/o-m-g/deepest.txt', src: 'expand/deep/deeper/deepest/deepest.txt'},
];
test.deepEqual(actual, expected, 'custom rename function should be used to build dest, post-flatten');

@@ -303,0 +319,0 @@ test.done();

@@ -16,27 +16,45 @@ 'use strict';

'normalize': function(test) {
test.expect(6);
var actual, expected;
test.expect(7);
var actual, expected, key, value;
var flatten = grunt.util._.flatten;
actual = grunt.task.normalizeMultiTaskFiles('src/*1.js', 'dist/built.js');
key = 'dist/built.js';
value = 'src/*1.js';
actual = grunt.task.normalizeMultiTaskFiles(value, key);
expected = [
{dest: 'dist/built.js', srcRaw: ['src/*1.js'], src: ['src/file1.js']}
{
dest: 'dist/built.js',
src: ['src/file1.js'],
orig: {dest: key, src: [value]},
},
];
test.deepEqual(actual, expected, 'should normalize destTarget: srcString.');
actual = grunt.task.normalizeMultiTaskFiles([['src/*1.js'], ['src/*2.js']], 'dist/built.js');
key = 'dist/built.js';
value = [['src/*1.js'], ['src/*2.js']];
actual = grunt.task.normalizeMultiTaskFiles(value, key);
expected = [
{dest: 'dist/built.js', srcRaw: ['src/*1.js', 'src/*2.js'], src: ['src/file1.js', 'src/file2.js']}
{
dest: 'dist/built.js',
src: ['src/file1.js', 'src/file2.js'],
orig: {dest: key, src: flatten(value)},
},
];
test.deepEqual(actual, expected, 'should normalize destTarget: srcArray.');
actual = grunt.task.normalizeMultiTaskFiles({
value = {
src: ['src/*1.js', 'src/*2.js'],
dest: 'dist/built.js'
}, 'target');
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{dest: 'dist/built.js', srcRaw: ['src/*1.js', 'src/*2.js'], src: ['src/file1.js', 'src/file2.js']}
{
dest: 'dist/built.js',
src: ['src/file1.js', 'src/file2.js'],
orig: value,
},
];
test.deepEqual(actual, expected, 'should normalize target: {src: srcStuff, dest: destStuff}.');
actual = grunt.task.normalizeMultiTaskFiles({
value = {
files: {

@@ -46,10 +64,19 @@ 'dist/built-a.js': 'src/*1.js',

}
}, 'target');
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{dest: 'dist/built-a.js', srcRaw: ['src/*1.js'], src: ['src/file1.js']},
{dest: 'dist/built-b.js', srcRaw: ['src/*1.js', 'src/*2.js'], src: ['src/file1.js', 'src/file2.js']}
{
dest: 'dist/built-a.js',
src: ['src/file1.js'],
orig: {dest: 'dist/built-a.js', src: [value.files['dist/built-a.js']]},
},
{
dest: 'dist/built-b.js',
src: ['src/file1.js', 'src/file2.js'],
orig: {dest: 'dist/built-b.js', src: flatten(value.files['dist/built-b.js'])},
},
];
test.deepEqual(actual, expected, 'should normalize target: {files: {destTarget: srcStuff, ...}}.');
actual = grunt.task.normalizeMultiTaskFiles({
value = {
files: [

@@ -59,49 +86,177 @@ {'dist/built-a.js': 'src/*.whoops'},

]
}, 'target');
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{dest: 'dist/built-a.js', srcRaw: ['src/*.whoops'], src: []},
{dest: 'dist/built-b.js', srcRaw: ['src/*1.js', 'src/*2.js'], src: ['src/file1.js', 'src/file2.js']}
{
dest: 'dist/built-a.js',
src: [],
orig: {dest: Object.keys(value.files[0])[0], src: [value.files[0]['dist/built-a.js']]},
},
{
dest: 'dist/built-b.js',
src: ['src/file1.js', 'src/file2.js'],
orig: {dest: Object.keys(value.files[1])[0], src: flatten(value.files[1]['dist/built-b.js'])},
},
];
test.deepEqual(actual, expected, 'should normalize target: {files: [{destTarget: srcStuff}, ...]}.');
actual = grunt.task.normalizeMultiTaskFiles({
value = {
files: [
{dest: 'dist/built-a.js', src: 'src/*2.js'},
{dest: 'dist/built-a.js', src: ['src/*2.js']},
{dest: 'dist/built-b.js', src: ['src/*1.js', 'src/*2.js']}
]
}, 'target');
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{dest: 'dist/built-a.js', srcRaw: ['src/*2.js'], src: ['src/file2.js']},
{dest: 'dist/built-b.js', srcRaw: ['src/*1.js', 'src/*2.js'], src: ['src/file1.js', 'src/file2.js']}
{
dest: 'dist/built-a.js',
src: ['src/file2.js'],
orig: value.files[0],
},
{
dest: 'dist/built-b.js',
src: ['src/file1.js', 'src/file2.js'],
orig: value.files[1],
},
];
test.deepEqual(actual, expected, 'should normalize target: {files: [{src: srcStuff, dest: destStuff}, ...]}.');
value = {
files: [
{dest: 'dist/built-a.js', src: ['src/*2.js'], foo: 123, bar: true},
{dest: 'dist/built-b.js', src: ['src/*1.js', 'src/*2.js'], foo: 456, bar: null}
]
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: 'dist/built-a.js',
src: ['src/file2.js'],
foo: 123,
bar: true,
orig: value.files[0],
},
{
dest: 'dist/built-b.js',
src: ['src/file1.js', 'src/file2.js'],
foo: 456,
bar: null,
orig: value.files[1],
},
];
test.deepEqual(actual, expected, 'should propagate extra properties.');
test.done();
},
'template processing': function(test) {
test.expect(1);
'nonull': function(test) {
test.expect(2);
var actual, expected, value;
// Processing "TEST" recursively should return "123"
grunt.config.set(['TEST'], '<%= TEST2.PROP %>');
grunt.config.set(['TEST2'], {
PROP: '<%= TEST2.PROP1 %><%= TEST2.PROP2 + TEST2.PROP3 %>',
PROP1: '1',
PROP2: '2',
PROP3: '3'
});
value = {
src: ['src/xxx*.js', 'src/yyy*.js'],
dest: 'dist/built.js',
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: value.dest,
src: [],
orig: value,
},
];
test.deepEqual(actual, expected, 'if nonull is not set, should not include non-matching patterns.');
var actual = grunt.task.normalizeMultiTaskFiles({
value = {
src: ['src/xxx*.js', 'src/yyy*.js'],
dest: 'dist/built.js',
nonull: true,
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: value.dest,
src: value.src,
nonull: true,
orig: value,
},
];
test.deepEqual(actual, expected, 'if nonull is set, should include non-matching patterns.');
test.done();
},
'expandMapping': function(test) {
test.expect(3);
var actual, expected, value;
value = {
files: [
{dest: 'dist/built-<%= TEST %>-a.js', src: 'src/file?-<%= TEST %>.js'},
{dest: 'dist/built-<%= TEST %>-b.js', src: ['src/*1-<%= TEST %>.js', 'src/*2-<%= TEST %>.js']}
{dest: 'dist/', src: ['src/file?.js'], expand: true},
{dest: 'dist/', src: ['file?.js'], expand: true, cwd: 'src'},
]
}, 'target');
var expected = [
{dest: 'dist/built-123-a.js', srcRaw: ['src/file?-123.js'], src: ['src/file1-123.js', 'src/file2-123.js']},
{dest: 'dist/built-123-b.js', srcRaw: ['src/*1-123.js', 'src/*2-123.js'], src: ['src/file1-123.js', 'src/file2-123.js']}
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: 'dist/src/file1.js', src: ['src/file1.js'],
orig: value.files[0],
},
{
dest: 'dist/src/file2.js', src: ['src/file2.js'],
orig: value.files[0],
},
{
dest: 'dist/file1.js', src: ['src/file1.js'],
orig: value.files[1],
},
{
dest: 'dist/file2.js', src: ['src/file2.js'],
orig: value.files[1],
},
];
test.deepEqual(actual, expected, 'should process templates recursively.');
test.deepEqual(actual, expected, 'expand to file mapping, removing cwd from destination paths.');
value = {
files: [
{dest: 'dist/', src: ['src/file?.js'], expand: true, flatten: true},
]
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: 'dist/file1.js', src: ['src/file1.js'],
orig: value.files[0],
},
{
dest: 'dist/file2.js', src: ['src/file2.js'],
orig: value.files[0],
},
];
test.deepEqual(actual, expected, 'expand to file mapping, flattening destination paths.');
value = {
files: [
{
dest: 'dist/',
src: ['src/file?.js'],
expand: true,
rename: function(destBase, destPath) {
return destBase + 'min/' + destPath.replace(/(\.js)$/, '.min$1');
},
},
]
};
actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
expected = [
{
dest: 'dist/min/src/file1.min.js', src: ['src/file1.js'],
orig: value.files[0],
},
{
dest: 'dist/min/src/file2.min.js', src: ['src/file2.js'],
orig: value.files[0],
},
];
test.deepEqual(actual, expected, 'expand to file mapping, renaming files.');
test.done();
}
},
};

@@ -20,2 +20,10 @@ /*

build: '123',
mappings: {
cwd: 'src/',
dest: 'foo/',
ext: '.bar',
rename: function(destBase, destPath) {
return destBase + 'baz/' + destPath.replace(/\.js$/, '<%= mappings.ext %>');
},
},
run: {

@@ -63,2 +71,25 @@ options: {a: 1, b: 11},

},
// File mapping options can be specified in these 2 formats.
built_mapping: {
options: {a: 6, c: 66},
expand: true,
cwd: '<%= mappings.cwd %>',
src: ['*1.js', '*2.js'],
dest: '<%= mappings.dest %>',
rename: '<%= mappings.rename %>',
extra: 123
},
long3_mapping: {
options: {a: 7, c: 77},
files: [
{
expand: true,
cwd: '<%= mappings.cwd %>',
src: ['*1.js', '*2.js'],
dest: '<%= mappings.dest %>',
rename: '<%= mappings.rename %>',
extra: 123
}
]
},
// Need to ensure the task function is run if no files or options were

@@ -76,11 +107,6 @@ // specified!

var key = this.nameArgs;
var result = results[key];
if (!result) {
result = results[key] = [];
}
result.push({
results[key] = {
options: this.options({d: 9}),
file: this.file
});
files: this.files,
};
// Test asynchronous-ness.

@@ -100,98 +126,180 @@ var done;

var expecteds = {
'run:dist/built.js': [
{
options: {a: 1, b: 11, d: 9},
file: {
'run:no_files_or_options': {
options: {a: 1, b: 11, d: 9},
files: [],
},
'run:dist/built.js': {
options: {a: 1, b: 11, d: 9},
files: [
{
dest: 'dist/built.js',
srcRaw: ['src/*1.js'],
src: ['src/file1.js'],
orig: {
dest: 'dist/built.js',
src: ['src/*1.js'],
},
},
},
],
'run:dist/built1.js': [
{
options: {a: 1, b: 11, d: 9},
file: {
]
},
'run:dist/built1.js': {
options: {a: 1, b: 11, d: 9},
files: [
{
dest: 'dist/built1.js',
srcRaw: ['src/*1.js', 'src/*2.js'],
src: ['src/file1.js', 'src/file2.js'],
orig: {
dest: 'dist/built1.js',
src: ['src/*1.js', 'src/*2.js'],
},
},
},
],
'run:built': [
{
options: {a: 2, b: 11, c: 22, d: 9},
file: {
]
},
'run:built': {
options: {a: 2, b: 11, c: 22, d: 9},
files: [
{
dest: 'dist/built-123.js',
srcRaw: ['src/*1.js', 'src/*2.js'],
src: ['src/file1.js', 'src/file2.js'],
extra: 123,
orig: {
dest: 'dist/built-123.js',
src: ['src/*1.js', 'src/*2.js'],
extra: 123,
},
},
},
],
'run:long1': [
{
options: {a: 3, b: 11, c: 33, d: 9},
file: {
],
},
'run:long1': {
options: {a: 3, b: 11, c: 33, d: 9},
files: [
{
dest: 'dist/built-123-a.js',
srcRaw: ['src/*1.js'],
src: ['src/file1.js'],
orig: {
dest: 'dist/built-123-a.js',
src: ['src/*1.js'],
},
},
},
{
options: {a: 3, b: 11, c: 33, d: 9},
file: {
{
dest: 'dist/built-123-b.js',
srcRaw: ['src/*1.js', 'src/*2.js'],
src: ['src/file1.js', 'src/file2.js'],
orig: {
dest: 'dist/built-123-b.js',
src: ['src/*1.js', 'src/*2.js'],
},
},
},
],
'run:long2': [
{
options: {a: 4, b: 11, c: 44, d: 9},
file: {
],
},
'run:long2': {
options: {a: 4, b: 11, c: 44, d: 9},
files: [
{
dest: 'dist/built-123-a.js',
srcRaw: ['src/*.whoops'],
src: [],
orig: {
dest: 'dist/built-123-a.js',
src: ['src/*.whoops'],
},
},
},
{
options: {a: 4, b: 11, c: 44, d: 9},
file: {
{
dest: 'dist/built-123-b.js',
srcRaw: ['src/*1.js', 'src/*2.js'],
src: ['src/file1.js', 'src/file2.js'],
orig: {
dest: 'dist/built-123-b.js',
src: ['src/*1.js', 'src/*2.js'],
},
},
},
],
'run:long3': [
{
options: {a: 5, b: 11, c: 55, d: 9},
file: {
],
},
'run:long3': {
options: {a: 5, b: 11, c: 55, d: 9},
files: [
{
dest: 'dist/built-123-a.js',
srcRaw: ['src/*2.js'],
src: ['src/file2.js'],
extra: 456,
orig: {
dest: 'dist/built-123-a.js',
src: ['src/*2.js'],
extra: 456,
},
},
},
{
options: {a: 5, b: 11, c: 55, d: 9},
file: {
{
dest: 'dist/built-123-b.js',
srcRaw: ['src/*1.js', 'src/*2.js'],
src: ['src/file1.js', 'src/file2.js'],
extra: 789,
orig: {
src: ['src/*1.js', 'src/*2.js'],
dest: 'dist/built-123-b.js',
extra: 789,
},
},
},
],
'run:no_files_or_options': [
{
options: {a: 1, b: 11, d: 9},
file: {},
},
],
};
],
},
'run:built_mapping': {
options: {a: 6, b: 11, c: 66, d: 9},
files: [
{
dest: 'foo/baz/file1.bar',
src: ['src/file1.js'],
extra: 123,
orig: {
expand: true,
cwd: grunt.config.get('mappings.cwd'),
src: ['*1.js', '*2.js'],
dest: grunt.config.get('mappings.dest'),
rename: grunt.config.get('run.built_mapping.rename'),
extra: 123,
},
},
{
dest: 'foo/baz/file2.bar',
src: ['src/file2.js'],
extra: 123,
orig: {
expand: true,
cwd: grunt.config.get('run.built_mapping.cwd'),
src: ['*1.js', '*2.js'],
dest: grunt.config.get('run.built_mapping.dest'),
rename: grunt.config.get('run.built_mapping.rename'),
extra: 123,
},
},
],
},
'run:long3_mapping': {
options: {a: 7, b: 11, c: 77, d: 9},
files: [
{
dest: 'foo/baz/file1.bar',
src: ['src/file1.js'],
extra: 123,
orig: {
expand: true,
cwd: grunt.config.get('mappings.cwd'),
src: ['*1.js', '*2.js'],
dest: grunt.config.get('mappings.dest'),
rename: grunt.config.get('mappings.rename'),
extra: 123,
},
},
{
dest: 'foo/baz/file2.bar',
src: ['src/file2.js'],
extra: 123,
orig: {
expand: true,
cwd: grunt.config.get('mappings.cwd'),
src: ['*1.js', '*2.js'],
dest: grunt.config.get('mappings.dest'),
rename: grunt.config.get('run.built_mapping.rename'),
extra: 123,
},
},
],
},
};
var assert = require('assert');
var difflet = require('difflet')({indent: 2, comment: true});
var test = function(name, fn) {

@@ -202,4 +310,3 @@ try {

grunt.log.subhead('Assertion Failure in ' + name);
console.log('Actual\n', JSON.stringify(err.actual));
console.log('Expected\n', JSON.stringify(err.expected));
console.log(difflet.compare(err.expected, err.actual));
throw new Error(err.message);

@@ -250,2 +357,6 @@ }

'test:long3',
'run:built_mapping',
'test:built_mapping',
'run:long3_mapping',
'test:long3_mapping',
'run',

@@ -252,0 +363,0 @@ 'test:all',

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc