Demo for query storing
Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/grunt/lib/grunt.js b/node_modules/grunt/lib/grunt.js
new file mode 100644
index 0000000..0253333
--- /dev/null
+++ b/node_modules/grunt/lib/grunt.js
@@ -0,0 +1,174 @@
+'use strict';
+
+// Nodejs libs.
+var path = require('path');
+
+// This allows grunt to require() .coffee files.
+try {
+ // Note: grunt no longer depends on CoffeeScript, it will only use it if it is intentionally
+ // installed in the project.
+ require('coffeescript/register');
+} catch (e) {
+ // This is fine, and will cause no problems so long as the user doesn't load .coffee files.
+ // Print a useful error if we attempt to load a .coffee file.
+ if (require.extensions) {
+ var FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'];
+ for (var i = 0; i < FILE_EXTENSIONS.length; i++) {
+ require.extensions[FILE_EXTENSIONS[i]] = function() {
+ throw new Error(
+ 'Grunt attempted to load a .coffee file but CoffeeScript was not installed.\n' +
+ 'Please run `npm install --dev coffeescript` to enable loading CoffeeScript.'
+ );
+ };
+ }
+ }
+}
+
+// The module to be exported.
+var grunt = module.exports = {};
+
+// Expose internal grunt libs.
+function gRequire(name) {
+ return grunt[name] = require('./grunt/' + name);
+}
+
+var util = require('grunt-legacy-util');
+grunt.util = util;
+grunt.util.task = require('./util/task');
+
+var Log = require('grunt-legacy-log').Log;
+var log = new Log({grunt: grunt});
+grunt.log = log;
+
+gRequire('template');
+gRequire('event');
+var fail = gRequire('fail');
+gRequire('file');
+var option = gRequire('option');
+var config = gRequire('config');
+var task = gRequire('task');
+var help = gRequire('help');
+gRequire('cli');
+var verbose = grunt.verbose = log.verbose;
+
+// Expose some grunt metadata.
+grunt.package = require('../package.json');
+grunt.version = grunt.package.version;
+
+// Expose specific grunt lib methods on grunt.
+function gExpose(obj, methodName, newMethodName) {
+ grunt[newMethodName || methodName] = obj[methodName].bind(obj);
+}
+gExpose(task, 'registerTask');
+gExpose(task, 'registerMultiTask');
+gExpose(task, 'registerInitTask');
+gExpose(task, 'renameTask');
+gExpose(task, 'loadTasks');
+gExpose(task, 'loadNpmTasks');
+gExpose(config, 'init', 'initConfig');
+gExpose(fail, 'warn');
+gExpose(fail, 'fatal');
+
+// Expose the task interface. I've never called this manually, and have no idea
+// how it will work. But it might.
+grunt.tasks = function(tasks, options, done) {
+ // Update options with passed-in options.
+ option.init(options);
+
+ // Display the grunt version and quit if the user did --version.
+ var _tasks, _options;
+ if (option('version')) {
+ // Not --verbose.
+ log.writeln('grunt v' + grunt.version);
+
+ if (option('verbose')) {
+ // --verbose
+ verbose.writeln('Install path: ' + path.resolve(__dirname, '..'));
+ // Yes, this is a total hack, but we don't want to log all that verbose
+ // task initialization stuff here.
+ grunt.log.muted = true;
+ // Initialize task system so that available tasks can be listed.
+ grunt.task.init([], {help: true});
+ // Re-enable logging.
+ grunt.log.muted = false;
+
+ // Display available tasks (for shell completion, etc).
+ _tasks = Object.keys(grunt.task._tasks).sort();
+ verbose.writeln('Available tasks: ' + _tasks.join(' '));
+
+ // Display available options (for shell completion, etc).
+ _options = [];
+ Object.keys(grunt.cli.optlist).forEach(function(long) {
+ var o = grunt.cli.optlist[long];
+ _options.push('--' + (o.negate ? 'no-' : '') + long);
+ if (o.short) { _options.push('-' + o.short); }
+ });
+ verbose.writeln('Available options: ' + _options.join(' '));
+ }
+
+ return;
+ }
+
+ // Init colors.
+ log.initColors();
+
+ // Display help and quit if the user did --help.
+ if (option('help')) {
+ help.display();
+ return;
+ }
+
+ // A little header stuff.
+ verbose.header('Initializing').writeflags(option.flags(), 'Command-line options');
+
+ // Determine and output which tasks will be run.
+ var tasksSpecified = tasks && tasks.length > 0;
+ tasks = task.parseArgs([tasksSpecified ? tasks : 'default']);
+
+ // Initialize tasks.
+ task.init(tasks, options);
+
+ verbose.writeln();
+ if (!tasksSpecified) {
+ verbose.writeln('No tasks specified, running default tasks.');
+ }
+ verbose.writeflags(tasks, 'Running tasks');
+
+ // Handle otherwise unhandleable (probably asynchronous) exceptions.
+ var uncaughtHandler = function(e) {
+ fail.fatal(e, fail.code.TASK_FAILURE);
+ };
+ process.on('uncaughtException', uncaughtHandler);
+
+ // Report, etc when all tasks have completed.
+ task.options({
+ error: function(e) {
+ fail.warn(e, fail.code.TASK_FAILURE);
+ },
+ done: function() {
+ // Stop handling uncaught exceptions so that we don't leave any
+ // unwanted process-level side effects behind. There is no need to do
+ // this in the error callback, because fail.warn() will either kill
+ // the process, or with --force keep on going all the way here.
+ process.removeListener('uncaughtException', uncaughtHandler);
+
+ // Output a final fail / success report.
+ fail.report();
+
+ if (done) {
+ // Execute "done" function when done (only if passed, of course).
+ done();
+ } else {
+ // Otherwise, explicitly exit.
+ util.exit(0);
+ }
+ }
+ });
+
+ // Execute all tasks, in order. Passing each task individually in a forEach
+ // allows the error callback to execute multiple times.
+ tasks.forEach(function(name) { task.run(name); });
+ // Run tasks async internally to reduce call-stack, per:
+ // https://github.com/gruntjs/grunt/pull/1026
+ task.start({asyncDone: true});
+};
diff --git a/node_modules/grunt/lib/grunt/cli.js b/node_modules/grunt/lib/grunt/cli.js
new file mode 100644
index 0000000..1252f54
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/cli.js
@@ -0,0 +1,55 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// External libs.
+var nopt = require('nopt');
+var gruntOptions = require('grunt-known-options');
+
+// This is only executed when run via command line.
+var cli = module.exports = function(options, done) {
+ // CLI-parsed options override any passed-in "default" options.
+ if (options) {
+ // For each default option...
+ Object.keys(options).forEach(function(key) {
+ if (!(key in cli.options)) {
+ // If this option doesn't exist in the parsed cli.options, add it in.
+ cli.options[key] = options[key];
+ } else if (cli.optlist[key].type === Array) {
+ // If this option's type is Array, append it to any existing array
+ // (or create a new array).
+ [].push.apply(cli.options[key], options[key]);
+ }
+ });
+ }
+
+ // Run tasks.
+ grunt.tasks(cli.tasks, cli.options, done);
+};
+
+// Default options.
+var optlist = cli.optlist = gruntOptions;
+
+// Parse `optlist` into a form that nopt can handle.
+var aliases = {};
+var known = {};
+
+Object.keys(optlist).forEach(function(key) {
+ var short = optlist[key].short;
+ if (short) {
+ aliases[short] = '--' + key;
+ }
+ known[key] = optlist[key].type;
+});
+
+var parsed = nopt(known, aliases, process.argv, 2);
+cli.tasks = parsed.argv.remain;
+cli.options = parsed;
+delete parsed.argv;
+
+// Initialize any Array options that weren't initialized.
+Object.keys(optlist).forEach(function(key) {
+ if (optlist[key].type === Array && !(key in cli.options)) {
+ cli.options[key] = [];
+ }
+});
diff --git a/node_modules/grunt/lib/grunt/config.js b/node_modules/grunt/lib/grunt/config.js
new file mode 100644
index 0000000..ef2bf80
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/config.js
@@ -0,0 +1,115 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// Get/set config data. If value was passed, set. Otherwise, get.
+var config = module.exports = function(prop, value) {
+ if (arguments.length === 2) {
+ // Two arguments were passed, set the property's value.
+ return config.set(prop, value);
+ } else {
+ // Get the property's value (or the entire data object).
+ return config.get(prop);
+ }
+};
+
+// The actual config data.
+config.data = {};
+
+// Escape any . in name with \. so dot-based namespacing works properly.
+config.escape = function(str) {
+ return str.replace(/\./g, '\\.');
+};
+
+// Return prop as a string.
+config.getPropString = function(prop) {
+ return Array.isArray(prop) ? prop.map(config.escape).join('.') : prop;
+};
+
+// Get raw, unprocessed config data.
+config.getRaw = function(prop) {
+ if (prop) {
+ // Prop was passed, get that specific property's value.
+ return grunt.util.namespace.get(config.data, config.getPropString(prop));
+ } else {
+ // No prop was passed, return the entire config.data object.
+ return config.data;
+ }
+};
+
+// Match '<%= FOO %>' where FOO is a propString, eg. foo or foo.bar but not
+// a method call like foo() or foo.bar().
+var propStringTmplRe = /^<%=\s*([a-z0-9_$]+(?:\.[a-z0-9_$]+)*)\s*%>$/i;
+
+// Get config data, recursively processing templates.
+config.get = function(prop) {
+ 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.
+ if (typeof value !== 'string') { return value; }
+ // If possible, access the specified property via config.get, in case it
+ // doesn't refer to a string, but instead refers to an object or array.
+ var matches = value.match(propStringTmplRe);
+ var result;
+ if (matches) {
+ result = config.get(matches[1]);
+ // If the result retrieved from the config data wasn't null or undefined,
+ // return it.
+ if (result != null) { return result; }
+ }
+ // Process the string as a template.
+ return grunt.template.process(value, {data: config.data});
+ });
+};
+
+// Set config data.
+config.set = function(prop, value) {
+ return grunt.util.namespace.set(config.data, config.getPropString(prop), value);
+};
+
+// Deep merge config data.
+config.merge = function(obj) {
+ grunt.util._.merge(config.data, obj);
+ return config.data;
+};
+
+// Initialize config data.
+config.init = function(obj) {
+ grunt.verbose.write('Initializing config...').ok();
+ // Initialize and return data.
+ return (config.data = obj || {});
+};
+
+// Test to see if required config params have been defined. If not, throw an
+// exception (use this inside of a task).
+config.requires = function() {
+ var p = grunt.util.pluralize;
+ var props = grunt.util.toArray(arguments).map(config.getPropString);
+ var msg = 'Verifying propert' + p(props.length, 'y/ies') +
+ ' ' + grunt.log.wordlist(props) + ' exist' + p(props.length, 's') +
+ ' in config...';
+ grunt.verbose.write(msg);
+ var failProps = config.data && props.filter(function(prop) {
+ return config.get(prop) == null;
+ }).map(function(prop) {
+ return '"' + prop + '"';
+ });
+ if (config.data && failProps.length === 0) {
+ grunt.verbose.ok();
+ return true;
+ } else {
+ grunt.verbose.or.write(msg);
+ grunt.log.error().error('Unable to process task.');
+ if (!config.data) {
+ throw grunt.util.error('Unable to load config.');
+ } else {
+ throw grunt.util.error('Required config propert' +
+ p(failProps.length, 'y/ies') + ' ' + failProps.join(', ') + ' missing.');
+ }
+ }
+};
diff --git a/node_modules/grunt/lib/grunt/event.js b/node_modules/grunt/lib/grunt/event.js
new file mode 100644
index 0000000..7ec1027
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/event.js
@@ -0,0 +1,7 @@
+'use strict';
+
+// External lib.
+var EventEmitter2 = require('eventemitter2').EventEmitter2;
+
+// Awesome.
+module.exports = new EventEmitter2({wildcard: true});
diff --git a/node_modules/grunt/lib/grunt/fail.js b/node_modules/grunt/lib/grunt/fail.js
new file mode 100644
index 0000000..631e249
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/fail.js
@@ -0,0 +1,75 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// The module to be exported.
+var fail = module.exports = {};
+
+// Error codes.
+fail.code = {
+ FATAL_ERROR: 1,
+ MISSING_GRUNTFILE: 2,
+ TASK_FAILURE: 3,
+ TEMPLATE_ERROR: 4,
+ INVALID_AUTOCOMPLETE: 5,
+ WARNING: 6,
+};
+
+// DRY it up!
+function writeln(e, mode) {
+ grunt.log.muted = false;
+ var msg = String(e.message || e);
+ if (!grunt.option('no-color')) { msg += '\x07'; } // Beep!
+ if (mode === 'warn') {
+ msg = 'Warning: ' + msg + ' ';
+ msg += (grunt.option('force') ? 'Used --force, continuing.'.underline : 'Use --force to continue.');
+ msg = msg.yellow;
+ } else {
+ msg = ('Fatal error: ' + msg).red;
+ }
+ grunt.log.writeln(msg);
+}
+
+// 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 occurred. Abort immediately.
+fail.fatal = function(e, errcode) {
+ writeln(e, 'fatal');
+ dumpStack(e);
+ grunt.util.exit(typeof errcode === 'number' ? errcode : fail.code.FATAL_ERROR);
+};
+
+// Keep track of error and warning counts.
+fail.errorcount = 0;
+fail.warncount = 0;
+
+// A warning occurred. Abort immediately unless -f or --force was used.
+fail.warn = function(e, errcode) {
+ var message = typeof e === 'string' ? e : e.message;
+ fail.warncount++;
+ writeln(message, 'warn');
+ // If -f or --force aren't used, stop script processing.
+ if (!grunt.option('force')) {
+ dumpStack(e);
+ grunt.log.writeln().fail('Aborted due to warnings.');
+ grunt.util.exit(typeof errcode === 'number' ? errcode : fail.code.WARNING);
+ }
+};
+
+// This gets called at the very end.
+fail.report = function() {
+ if (fail.warncount > 0) {
+ grunt.log.writeln().fail('Done, but with warnings.');
+ } else {
+ grunt.log.writeln().success('Done.');
+ }
+};
diff --git a/node_modules/grunt/lib/grunt/file.js b/node_modules/grunt/lib/grunt/file.js
new file mode 100644
index 0000000..7e0e2fb
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/file.js
@@ -0,0 +1,460 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// Nodejs libs.
+var fs = require('fs');
+var path = require('path');
+
+// The module to be exported.
+var file = module.exports = {};
+
+// External libs.
+file.glob = require('glob');
+file.minimatch = require('minimatch');
+file.findup = require('findup-sync');
+var YAML = require('js-yaml');
+var rimraf = require('rimraf');
+var iconv = require('iconv-lite');
+var mkdirp = require('mkdirp').sync;
+
+// Windows?
+var win32 = process.platform === 'win32';
+
+// Normalize \\ paths to / paths.
+var unixifyPath = function(filepath) {
+ if (win32) {
+ return filepath.replace(/\\/g, '/');
+ } else {
+ return filepath;
+ }
+};
+
+// Change the current base path (ie, CWD) to the specified path.
+file.setBase = function() {
+ var dirpath = path.join.apply(path, arguments);
+ process.chdir(dirpath);
+};
+
+// Process specified wildcard glob patterns or filenames against a
+// callback, excluding and uniquing files in the result set.
+var processPatterns = function(patterns, fn) {
+ // Filepaths to return.
+ var result = [];
+ // Iterate over flattened patterns array.
+ grunt.util._.flattenDeep(patterns).forEach(function(pattern) {
+ // If the first character is ! it should be omitted
+ var exclusion = pattern.indexOf('!') === 0;
+ // If the pattern is an exclusion, remove the !
+ if (exclusion) { pattern = pattern.slice(1); }
+ // Find all matching files for this pattern.
+ var matches = fn(pattern);
+ if (exclusion) {
+ // If an exclusion, remove matching files.
+ result = grunt.util._.difference(result, matches);
+ } else {
+ // Otherwise add matching files.
+ result = grunt.util._.union(result, matches);
+ }
+ });
+ return result;
+};
+
+// Match a filepath or filepaths against one or more wildcard patterns. Returns
+// all matching filepaths.
+file.match = function(options, patterns, filepaths) {
+ if (grunt.util.kindOf(options) !== 'object') {
+ filepaths = patterns;
+ patterns = options;
+ options = {};
+ }
+ // Return empty set if either patterns or filepaths was omitted.
+ if (patterns == null || filepaths == null) { return []; }
+ // Normalize patterns and filepaths to arrays.
+ if (!Array.isArray(patterns)) { patterns = [patterns]; }
+ if (!Array.isArray(filepaths)) { filepaths = [filepaths]; }
+ // Return empty set if there are no patterns or filepaths.
+ if (patterns.length === 0 || filepaths.length === 0) { return []; }
+ // Return all matching filepaths.
+ return processPatterns(patterns, function(pattern) {
+ return file.minimatch.match(filepaths, pattern, options);
+ });
+};
+
+// Match a filepath or filepaths against one or more wildcard patterns. Returns
+// true if any of the patterns match.
+file.isMatch = function() {
+ return file.match.apply(file, arguments).length > 0;
+};
+
+// Return an array of all file paths that match the given wildcard patterns.
+file.expand = function() {
+ var args = grunt.util.toArray(arguments);
+ // If the first argument is an options object, save those options to pass
+ // into the file.glob.sync method.
+ var options = grunt.util.kindOf(args[0]) === 'object' ? args.shift() : {};
+ // Use the first argument if it's an Array, otherwise convert the arguments
+ // object to an array and use that.
+ var patterns = Array.isArray(args[0]) ? args[0] : args;
+ // Return empty set if there are no patterns or filepaths.
+ if (patterns.length === 0) { return []; }
+ // Return all matching filepaths.
+ 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;
+};
+
+var pathSeparatorRe = /[\/\\]/g;
+
+// The "ext" option refers to either everything after the first dot (default)
+// or everything after the last dot.
+var extDotRe = {
+ first: /(\.[^\/]*)?$/,
+ last: /(\.[^\/\.]*)?$/,
+};
+
+// Build a multi task "files" object dynamically.
+file.expandMapping = function(patterns, destBase, options) {
+ options = grunt.util._.defaults({}, options, {
+ extDot: 'first',
+ rename: function(destBase, destPath) {
+ return path.join(destBase || '', destPath);
+ }
+ });
+ var files = [];
+ var fileByDest = {};
+ // Find all files matching pattern, using passed-in options.
+ file.expand(options, patterns).forEach(function(src) {
+ var destPath = src;
+ // Flatten?
+ if (options.flatten) {
+ destPath = path.basename(destPath);
+ }
+ // Change the extension?
+ if ('ext' in options) {
+ destPath = destPath.replace(extDotRe[options.extDot], options.ext);
+ }
+ // Generate destination filename.
+ var dest = options.rename(destBase, destPath, options);
+ // Prepend cwd to src path if necessary.
+ if (options.cwd) { src = path.join(options.cwd, src); }
+ // Normalize filepaths to be unix-style.
+ dest = dest.replace(pathSeparatorRe, '/');
+ src = src.replace(pathSeparatorRe, '/');
+ // Map correct src path to dest path.
+ if (fileByDest[dest]) {
+ // If dest already exists, push this src onto that dest's src array.
+ fileByDest[dest].src.push(src);
+ } else {
+ // Otherwise create a new src-dest file mapping object.
+ files.push({
+ src: [src],
+ dest: dest,
+ });
+ // And store a reference for later use.
+ fileByDest[dest] = files[files.length - 1];
+ }
+ });
+ return files;
+};
+
+// Like mkdir -p. Create a directory and any intermediary directories.
+file.mkdir = function(dirpath, mode) {
+ if (grunt.option('no-write')) { return; }
+ try {
+ mkdirp(dirpath, { mode: mode });
+ } catch (e) {
+ throw grunt.util.error('Unable to create directory "' + dirpath + '" (Error code: ' + e.code + ').', e);
+ }
+};
+
+// Recurse into a directory, executing callback for each file.
+file.recurse = function recurse(rootdir, callback, subdir) {
+ var abspath = subdir ? path.join(rootdir, subdir) : rootdir;
+ fs.readdirSync(abspath).forEach(function(filename) {
+ var filepath = path.join(abspath, filename);
+ if (fs.statSync(filepath).isDirectory()) {
+ recurse(rootdir, callback, unixifyPath(path.join(subdir || '', filename || '')));
+ } else {
+ callback(unixifyPath(filepath), rootdir, subdir, filename);
+ }
+ });
+};
+
+// The default file encoding to use.
+file.defaultEncoding = 'utf8';
+// Whether to preserve the BOM on file.read rather than strip it.
+file.preserveBOM = false;
+
+// Read a file, return its contents.
+file.read = function(filepath, options) {
+ if (!options) { options = {}; }
+ var contents;
+ grunt.verbose.write('Reading ' + filepath + '...');
+ try {
+ contents = fs.readFileSync(String(filepath));
+ // If encoding is not explicitly null, convert from encoded buffer to a
+ // string. If no encoding was specified, use the default.
+ if (options.encoding !== null) {
+ contents = iconv.decode(contents, options.encoding || file.defaultEncoding, {stripBOM: !file.preserveBOM});
+ }
+ grunt.verbose.ok();
+ return contents;
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Unable to read "' + filepath + '" file (Error code: ' + e.code + ').', e);
+ }
+};
+
+// Read a file, parse its contents, return an object.
+file.readJSON = function(filepath, options) {
+ var src = file.read(filepath, options);
+ var result;
+ grunt.verbose.write('Parsing ' + filepath + '...');
+ try {
+ result = JSON.parse(src);
+ grunt.verbose.ok();
+ return result;
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Unable to parse "' + filepath + '" file (' + e.message + ').', e);
+ }
+};
+
+// Read a YAML file, parse its contents, return an object.
+file.readYAML = function(filepath, options, yamlOptions) {
+ if (!options) { options = {}; }
+ if (!yamlOptions) { yamlOptions = {}; }
+
+ var src = file.read(filepath, options);
+ var result;
+ grunt.verbose.write('Parsing ' + filepath + '...');
+ try {
+ // use the recommended way of reading YAML files
+ // https://github.com/nodeca/js-yaml#safeload-string---options-
+ if (yamlOptions.unsafeLoad) {
+ result = YAML.load(src);
+ } else {
+ result = YAML.safeLoad(src);
+ }
+ grunt.verbose.ok();
+ return result;
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Unable to parse "' + filepath + '" file (' + e.message + ').', e);
+ }
+};
+
+// Write a file.
+file.write = function(filepath, contents, options) {
+ if (!options) { options = {}; }
+ var nowrite = grunt.option('no-write');
+ grunt.verbose.write((nowrite ? 'Not actually writing ' : 'Writing ') + filepath + '...');
+ // Create path, if necessary.
+ file.mkdir(path.dirname(filepath));
+ try {
+ // If contents is already a Buffer, don't try to encode it. If no encoding
+ // was specified, use the default.
+ if (!Buffer.isBuffer(contents)) {
+ contents = iconv.encode(contents, options.encoding || file.defaultEncoding);
+ }
+ // Actually write file.
+ if (!nowrite) {
+ fs.writeFileSync(filepath, contents, 'mode' in options ? {mode: options.mode} : {});
+ }
+ grunt.verbose.ok();
+ return true;
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Unable to write "' + filepath + '" file (Error code: ' + e.code + ').', e);
+ }
+};
+
+// Read a file, optionally processing its content, then write the output.
+// Or read a directory, recursively creating directories, reading files,
+// processing content, writing output.
+file.copy = function copy(srcpath, destpath, options) {
+ if (file.isDir(srcpath)) {
+ // Copy a directory, recursively.
+ // Explicitly create new dest directory.
+ file.mkdir(destpath);
+ // Iterate over all sub-files/dirs, recursing.
+ fs.readdirSync(srcpath).forEach(function(filepath) {
+ copy(path.join(srcpath, filepath), path.join(destpath, filepath), options);
+ });
+ } else {
+ // Copy a single file.
+ file._copy(srcpath, destpath, options);
+ }
+};
+
+// Read a file, optionally processing its content, then write the output.
+file._copy = function(srcpath, destpath, options) {
+ if (!options) { options = {}; }
+ // If a process function was specified, and noProcess isn't true or doesn't
+ // match the srcpath, process the file's source.
+ var process = options.process && options.noProcess !== true &&
+ !(options.noProcess && file.isMatch(options.noProcess, srcpath));
+ // If the file will be processed, use the encoding as-specified. Otherwise,
+ // use an encoding of null to force the file to be read/written as a Buffer.
+ var readWriteOptions = process ? options : {encoding: null};
+ // Actually read the file.
+ var contents = file.read(srcpath, readWriteOptions);
+ if (process) {
+ grunt.verbose.write('Processing source...');
+ try {
+ contents = options.process(contents, srcpath, destpath);
+ grunt.verbose.ok();
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Error while processing "' + srcpath + '" file.', e);
+ }
+ }
+ // Abort copy if the process function returns false.
+ if (contents === false) {
+ grunt.verbose.writeln('Write aborted.');
+ } else {
+ file.write(destpath, contents, readWriteOptions);
+ }
+};
+
+// Delete folders and files recursively
+file.delete = function(filepath, options) {
+ filepath = String(filepath);
+
+ var nowrite = grunt.option('no-write');
+ if (!options) {
+ options = {force: grunt.option('force') || false};
+ }
+
+ grunt.verbose.write((nowrite ? 'Not actually deleting ' : 'Deleting ') + filepath + '...');
+
+ if (!file.exists(filepath)) {
+ grunt.verbose.error();
+ grunt.log.warn('Cannot delete nonexistent file.');
+ return false;
+ }
+
+ // Only delete cwd or outside cwd if --force enabled. Be careful, people!
+ if (!options.force) {
+ if (file.isPathCwd(filepath)) {
+ grunt.verbose.error();
+ grunt.fail.warn('Cannot delete the current working directory.');
+ return false;
+ } else if (!file.isPathInCwd(filepath)) {
+ grunt.verbose.error();
+ grunt.fail.warn('Cannot delete files outside the current working directory.');
+ return false;
+ }
+ }
+
+ try {
+ // Actually delete. Or not.
+ if (!nowrite) {
+ rimraf.sync(filepath);
+ }
+ grunt.verbose.ok();
+ return true;
+ } catch (e) {
+ grunt.verbose.error();
+ throw grunt.util.error('Unable to delete "' + filepath + '" file (' + e.message + ').', e);
+ }
+};
+
+// True if the file path exists.
+file.exists = function() {
+ var filepath = path.join.apply(path, arguments);
+ return fs.existsSync(filepath);
+};
+
+// True if the file is a symbolic link.
+file.isLink = function() {
+ var filepath = path.join.apply(path, arguments);
+ try {
+ return fs.lstatSync(filepath).isSymbolicLink();
+ } catch (e) {
+ if (e.code === 'ENOENT') {
+ // The file doesn't exist, so it's not a symbolic link.
+ return false;
+ }
+ throw grunt.util.error('Unable to read "' + filepath + '" file (Error code: ' + e.code + ').', e);
+ }
+};
+
+// True if the path is a directory.
+file.isDir = function() {
+ var filepath = path.join.apply(path, arguments);
+ return file.exists(filepath) && fs.statSync(filepath).isDirectory();
+};
+
+// True if the path is a file.
+file.isFile = function() {
+ var filepath = path.join.apply(path, arguments);
+ return file.exists(filepath) && fs.statSync(filepath).isFile();
+};
+
+// Is a given file path absolute?
+file.isPathAbsolute = function() {
+ var filepath = path.join.apply(path, arguments);
+ return path.isAbsolute(filepath);
+};
+
+// Do all the specified paths refer to the same path?
+file.arePathsEquivalent = function(first) {
+ first = path.resolve(first);
+ for (var i = 1; i < arguments.length; i++) {
+ if (first !== path.resolve(arguments[i])) { return false; }
+ }
+ return true;
+};
+
+// Are descendant path(s) contained within ancestor path? Note: does not test
+// if paths actually exist.
+file.doesPathContain = function(ancestor) {
+ ancestor = path.resolve(ancestor);
+ var relative;
+ for (var i = 1; i < arguments.length; i++) {
+ relative = path.relative(path.resolve(arguments[i]), ancestor);
+ if (relative === '' || /\w+/.test(relative)) { return false; }
+ }
+ return true;
+};
+
+// Test to see if a filepath is the CWD.
+file.isPathCwd = function() {
+ var filepath = path.join.apply(path, arguments);
+ try {
+ return file.arePathsEquivalent(fs.realpathSync(process.cwd()), fs.realpathSync(filepath));
+ } catch (e) {
+ return false;
+ }
+};
+
+// Test to see if a filepath is contained within the CWD.
+file.isPathInCwd = function() {
+ var filepath = path.join.apply(path, arguments);
+ try {
+ return file.doesPathContain(fs.realpathSync(process.cwd()), fs.realpathSync(filepath));
+ } catch (e) {
+ return false;
+ }
+};
diff --git a/node_modules/grunt/lib/grunt/help.js b/node_modules/grunt/lib/grunt/help.js
new file mode 100644
index 0000000..d761ef5
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/help.js
@@ -0,0 +1,120 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// Nodejs libs.
+var path = require('path');
+
+// Set column widths.
+var col1len = 0;
+exports.initCol1 = function(str) {
+ col1len = Math.max(col1len, str.length);
+};
+exports.initWidths = function() {
+ // Widths for options/tasks table output.
+ var commandWidth = Math.max(col1len + 20, 76);
+ exports.widths = [1, col1len, 2, commandWidth - col1len];
+};
+
+// Render an array in table form.
+exports.table = function(arr) {
+ arr.forEach(function(item) {
+ grunt.log.writetableln(exports.widths, ['', grunt.util._.pad(item[0], col1len), '', item[1]]);
+ });
+};
+
+// Methods to run, in-order.
+exports.queue = [
+ 'initOptions',
+ 'initTasks',
+ 'initWidths',
+ 'header',
+ 'usage',
+ 'options',
+ 'optionsFooter',
+ 'tasks',
+ 'footer',
+];
+
+// Actually display stuff.
+exports.display = function() {
+ exports.queue.forEach(function(name) { exports[name](); });
+};
+
+// Header.
+exports.header = function() {
+ grunt.log.writeln('Grunt: The JavaScript Task Runner (v' + grunt.version + ')');
+};
+
+// Usage info.
+exports.usage = function() {
+ grunt.log.header('Usage');
+ grunt.log.writeln(' ' + path.basename(process.argv[1]) + ' [options] [task [task ...]]');
+};
+
+// Options.
+exports.initOptions = function() {
+ // Build 2-column array for table view.
+ exports._options = Object.keys(grunt.cli.optlist).map(function(long) {
+ var o = grunt.cli.optlist[long];
+ var col1 = '--' + (o.negate ? 'no-' : '') + long + (o.short ? ', -' + o.short : '');
+ exports.initCol1(col1);
+ return [col1, o.info];
+ });
+};
+
+exports.options = function() {
+ grunt.log.header('Options');
+ exports.table(exports._options);
+};
+
+exports.optionsFooter = function() {
+ grunt.log.writeln().writelns(
+ 'Options marked with * have methods exposed via the grunt API and should ' +
+ 'instead be specified inside the Gruntfile wherever possible.'
+ );
+};
+
+// Tasks.
+exports.initTasks = function() {
+ // Initialize task system so that the tasks can be listed.
+ grunt.task.init([], {help: true});
+
+ // Build object of tasks by info (where they were loaded from).
+ exports._tasks = [];
+ Object.keys(grunt.task._tasks).forEach(function(name) {
+ exports.initCol1(name);
+ var task = grunt.task._tasks[name];
+ exports._tasks.push(task);
+ });
+};
+
+exports.tasks = function() {
+ grunt.log.header('Available tasks');
+ if (exports._tasks.length === 0) {
+ grunt.log.writeln('(no tasks found)');
+ } else {
+ exports.table(exports._tasks.map(function(task) {
+ var info = task.info;
+ if (task.multi) { info += ' *'; }
+ return [task.name, info];
+ }));
+
+ grunt.log.writeln().writelns(
+ 'Tasks run in the order specified. Arguments may be passed to tasks that ' +
+ 'accept them by using colons, like "lint:files". Tasks marked with * are ' +
+ '"multi tasks" and will iterate over all sub-targets if no argument is ' +
+ 'specified.'
+ );
+ }
+
+ grunt.log.writeln().writelns(
+ 'The list of available tasks may change based on tasks directories or ' +
+ 'grunt plugins specified in the Gruntfile or via command-line options.'
+ );
+};
+
+// Footer.
+exports.footer = function() {
+ grunt.log.writeln().writeln('For more information, see http://gruntjs.com/');
+};
diff --git a/node_modules/grunt/lib/grunt/option.js b/node_modules/grunt/lib/grunt/option.js
new file mode 100644
index 0000000..bfb4074
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/option.js
@@ -0,0 +1,38 @@
+'use strict';
+
+// The actual option data.
+var data = {};
+
+// Get or set an option value.
+var option = module.exports = function(key, value) {
+ var no = key.match(/^no-(.+)$/);
+ if (arguments.length === 2) {
+ return (data[key] = value);
+ } else if (no) {
+ return data[no[1]] === false;
+ } else {
+ return data[key];
+ }
+};
+
+// Initialize option data.
+option.init = function(obj) {
+ return (data = obj || {});
+};
+
+// List of options as flags.
+option.flags = function() {
+ return Object.keys(data).filter(function(key) {
+ // Don't display empty arrays.
+ return !(Array.isArray(data[key]) && data[key].length === 0);
+ }).map(function(key) {
+ var val = data[key];
+ return '--' + (val === false ? 'no-' : '') + key +
+ (typeof val === 'boolean' ? '' : '=' + val);
+ });
+};
+
+// Get all option keys
+option.keys = function() {
+ return Object.keys(data);
+};
diff --git a/node_modules/grunt/lib/grunt/task.js b/node_modules/grunt/lib/grunt/task.js
new file mode 100644
index 0000000..ffd119e
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/task.js
@@ -0,0 +1,471 @@
+'use strict';
+
+// Keep track of the number of log.error() calls and the last specified tasks message.
+var errorcount, lastInfo;
+
+var grunt = require('../grunt');
+
+// Nodejs libs.
+var path = require('path');
+
+// Extend generic "task" util lib.
+var parent = grunt.util.task.create();
+
+// The module to be exported.
+var task = module.exports = Object.create(parent);
+
+// A temporary registry of tasks and metadata.
+var registry = {tasks: [], untasks: [], meta: {}};
+
+// Number of levels of recursion when loading tasks in collections.
+var loadTaskDepth = 0;
+
+// Override built-in registerTask.
+task.registerTask = function(name) {
+ // Add task to registry.
+ registry.tasks.push(name);
+ // Register task.
+ parent.registerTask.apply(task, arguments);
+ // This task, now that it's been registered.
+ var thisTask = task._tasks[name];
+ // Metadata about the current task.
+ thisTask.meta = grunt.util._.clone(registry.meta);
+ // Override task function.
+ var _fn = thisTask.fn;
+ thisTask.fn = function(arg) {
+ // Guaranteed to always be the actual task name.
+ var name = thisTask.name;
+ // Initialize the errorcount for this task.
+ errorcount = grunt.fail.errorcount;
+ // Return the number of errors logged during this task.
+ Object.defineProperty(this, 'errorCount', {
+ enumerable: true,
+ get: function() {
+ return grunt.fail.errorcount - errorcount;
+ }
+ });
+ // Expose task.requires on `this`.
+ this.requires = task.requires.bind(task);
+ // Expose config.requires on `this`.
+ this.requiresConfig = grunt.config.requires;
+ // Return an options object with the specified defaults overwritten by task-
+ // specific overrides, via the "options" property.
+ this.options = function() {
+ var args = [{}].concat(grunt.util.toArray(arguments)).concat([
+ grunt.config([name, 'options'])
+ ]);
+ var options = grunt.util._.extend.apply(null, args);
+ grunt.verbose.writeflags(options, 'Options');
+ return options;
+ };
+ // If this task was an alias or a multi task called without a target,
+ // only log if in verbose mode.
+ var logger = _fn.alias || (thisTask.multi && (!arg || arg === '*')) ? 'verbose' : 'log';
+ // Actually log.
+ grunt[logger].header('Running "' + this.nameArgs + '"' +
+ (this.name !== this.nameArgs ? ' (' + this.name + ')' : '') + ' task');
+ // If --debug was specified, log the path to this task's source file.
+ grunt[logger].debug('Task source: ' + thisTask.meta.filepath);
+ // Actually run the task.
+ return _fn.apply(this, arguments);
+ };
+ return task;
+};
+
+// Multi task targets can't start with _ or be a reserved property (options).
+function isValidMultiTaskTarget(target) {
+ return !/^_|^options$/.test(target);
+}
+
+// Normalize multi task files.
+task.normalizeMultiTaskFiles = function(data, target) {
+ var prop, obj;
+ var files = [];
+ if (grunt.util.kindOf(data) === 'object') {
+ if ('src' in data || 'dest' in data) {
+ obj = {};
+ for (prop in data) {
+ if (prop !== 'options') {
+ obj[prop] = data[prop];
+ }
+ }
+ files.push(obj);
+ } else if (grunt.util.kindOf(data.files) === 'object') {
+ for (prop in data.files) {
+ files.push({src: data.files[prop], dest: grunt.config.process(prop)});
+ }
+ } else if (Array.isArray(data.files)) {
+ grunt.util._.flattenDeep(data.files).forEach(function(obj) {
+ var prop;
+ if ('src' in obj || 'dest' in obj) {
+ files.push(obj);
+ } else {
+ for (prop in obj) {
+ files.push({src: obj[prop], dest: grunt.config.process(prop)});
+ }
+ }
+ });
+ }
+ } else {
+ files.push({src: data, dest: grunt.config.process(target)});
+ }
+
+ // If no src/dest or files were specified, return an empty files array.
+ if (files.length === 0) {
+ grunt.verbose.writeln('File: ' + '[no files]'.yellow);
+ return [];
+ }
+
+ // 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;
+ });
+ }
+
+ // 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(result, 'src', {
+ enumerable: true,
+ get: function fn() {
+ var src;
+ if (!('result' in fn)) {
+ 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);
+ }
+ return fn.result;
+ }
+ });
+ }
+
+ 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]'.yellow);
+ }
+ if ('dest' in obj) {
+ output.push('-> ' + (obj.dest ? String(obj.dest).cyan : '[no dest]'.yellow));
+ }
+ if (output.length > 0) {
+ grunt.verbose.writeln('Files: ' + output.join(' '));
+ }
+ });
+ }
+
+ return files;
+};
+
+// This is the most common "multi task" pattern.
+task.registerMultiTask = function(name, info, fn) {
+ // If optional "info" string is omitted, shuffle arguments a bit.
+ if (fn == null) {
+ fn = info;
+ info = 'Custom multi task.';
+ }
+ // Store a reference to the task object, in case the task gets renamed.
+ var thisTask;
+ task.registerTask(name, info, function(target) {
+ // Guaranteed to always be the actual task name.
+ var name = thisTask.name;
+ // Arguments (sans target) as an array.
+ 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, this.args);
+ } else if (!isValidMultiTaskTarget(target)) {
+ throw new Error('Invalid target "' + target + '" specified.');
+ }
+ // Fail if any required config properties have been omitted.
+ this.requiresConfig([name, target]);
+ // Return an options object with the specified defaults overwritten 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 : {}
+ ]);
+ var options = grunt.util._.extend.apply(null, args);
+ grunt.verbose.writeflags(options, 'Options');
+ return options;
+ };
+ // 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);
+ // 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().map('src').flatten().uniq().value();
+ }.bind(this)
+ });
+ // Call original task function, passing in the target and any other args.
+ return fn.apply(this, this.args);
+ });
+
+ thisTask = task._tasks[name];
+ thisTask.multi = true;
+};
+
+// Init tasks don't require properties in config, and as such will preempt
+// config loading errors.
+task.registerInitTask = function(name, info, fn) {
+ task.registerTask(name, info, fn);
+ task._tasks[name].init = true;
+};
+
+// Override built-in renameTask to use the registry.
+task.renameTask = function(oldname, newname) {
+ var result;
+ try {
+ // Actually rename task.
+ result = parent.renameTask.apply(task, arguments);
+ // Add and remove task.
+ registry.untasks.push(oldname);
+ registry.tasks.push(newname);
+ // Return result.
+ return result;
+ } catch (e) {
+ grunt.log.error(e.message);
+ }
+};
+
+// If a property wasn't passed, run all task targets in turn.
+task.runAllTargets = function(taskname, args) {
+ // Get an array of sub-property keys under the given config object.
+ var targets = Object.keys(grunt.config.getRaw(taskname) || {});
+ // Remove invalid target properties.
+ targets = targets.filter(isValidMultiTaskTarget);
+ // Fail if there are no actual properties to iterate over.
+ if (targets.length === 0) {
+ grunt.log.error('No "' + taskname + '" targets found.');
+ return false;
+ }
+ // Iterate over all targets, running a task for each.
+ targets.forEach(function(target) {
+ // Be sure to pass in any additionally specified args.
+ task.run([taskname, target].concat(args || []).join(':'));
+ });
+};
+
+// Load tasks and handlers from a given tasks file.
+var loadTaskStack = [];
+function loadTask(filepath) {
+ // In case this was called recursively, save registry for later.
+ loadTaskStack.push(registry);
+ // Reset registry.
+ registry = {tasks: [], untasks: [], meta: {info: lastInfo, filepath: filepath}};
+ var filename = path.basename(filepath);
+ var msg = 'Loading "' + filename + '" tasks...';
+ var regCount = 0;
+ var fn;
+ try {
+ // Load taskfile.
+ fn = require(path.resolve(filepath));
+ if (typeof fn === 'function') {
+ fn.call(grunt, grunt);
+ }
+ grunt.verbose.write(msg).ok();
+ // Log registered/renamed/unregistered tasks.
+ ['un', ''].forEach(function(prefix) {
+ var list = grunt.util._.chain(registry[prefix + 'tasks']).uniq().sort().value();
+ if (list.length > 0) {
+ regCount++;
+ grunt.verbose.writeln((prefix ? '- ' : '+ ') + grunt.log.wordlist(list));
+ }
+ });
+ if (regCount === 0) {
+ grunt.verbose.warn('No tasks were registered or unregistered.');
+ }
+ } catch (e) {
+ // Something went wrong.
+ grunt.log.write(msg).error().verbose.error(e.stack).or.error(e);
+ }
+ // Restore registry.
+ registry = loadTaskStack.pop() || {};
+}
+
+// Log a message when loading tasks.
+function loadTasksMessage(info) {
+ // Only keep track of names of top-level loaded tasks and collections,
+ // not sub-tasks.
+ if (loadTaskDepth === 0) { lastInfo = info; }
+ grunt.verbose.subhead('Registering ' + info + ' tasks.');
+}
+
+// Load tasks and handlers from a given directory.
+function loadTasks(tasksdir) {
+ try {
+ var files = grunt.file.glob.sync('*.{js,coffee}', {cwd: tasksdir, maxDepth: 1});
+ // Load tasks from files.
+ files.forEach(function(filename) {
+ loadTask(path.join(tasksdir, filename));
+ });
+ } catch (e) {
+ grunt.log.verbose.error(e.stack).or.error(e);
+ }
+}
+
+// Load tasks and handlers from a given directory.
+task.loadTasks = function(tasksdir) {
+ loadTasksMessage('"' + tasksdir + '"');
+ if (grunt.file.exists(tasksdir)) {
+ loadTasks(tasksdir);
+ } else {
+ grunt.log.error('Tasks directory "' + tasksdir + '" not found.');
+ }
+};
+
+// Load tasks and handlers from a given locally-installed Npm module (installed
+// relative to the base dir).
+task.loadNpmTasks = function(name) {
+ loadTasksMessage('"' + name + '" local Npm module');
+ var root = path.resolve('node_modules');
+ var pkgpath = path.join(root, name);
+ var pkgfile = path.join(pkgpath, 'package.json');
+ // If package does not exist where grunt expects it to be,
+ // try to find it using Node's package path resolution mechanism
+ if (!grunt.file.exists(pkgpath)) {
+ var nameParts = name.split('/');
+ // In case name points to directory inside module,
+ // get real name of the module with respect to scope (if any)
+ var normailzedName = (name[0] === '@' ? nameParts.slice(0,2).join('/') : nameParts[0]);
+ try {
+ pkgfile = require.resolve(normailzedName + '/package.json');
+ root = pkgfile.substr(0, pkgfile.length - normailzedName.length - '/package.json'.length);
+ } catch (err) {
+ grunt.log.error('Local Npm module "' + normailzedName + '" not found. Is it installed?');
+ return;
+ }
+ }
+ var pkg = grunt.file.exists(pkgfile) ? grunt.file.readJSON(pkgfile) : {keywords: []};
+
+ // Process collection plugins.
+ if (pkg.keywords && pkg.keywords.indexOf('gruntcollection') !== -1) {
+ loadTaskDepth++;
+ Object.keys(pkg.dependencies).forEach(function(depName) {
+ // Npm sometimes pulls dependencies out if they're shared, so find
+ // upwards if not found locally.
+ var filepath = grunt.file.findup('node_modules/' + depName, {
+ cwd: path.resolve('node_modules', name),
+ nocase: true
+ });
+ if (filepath) {
+ // Load this task plugin recursively.
+ task.loadNpmTasks(path.relative(root, filepath));
+ }
+ });
+ loadTaskDepth--;
+ return;
+ }
+
+ // Process task plugins.
+ var tasksdir = path.join(root, name, 'tasks');
+ if (grunt.file.exists(tasksdir)) {
+ loadTasks(tasksdir);
+ } else {
+ grunt.log.error('Local Npm module "' + name + '" not found. Is it installed?');
+ }
+};
+
+// Initialize tasks.
+task.init = function(tasks, options) {
+ if (!options) { options = {}; }
+
+ // Were only init tasks specified?
+ var allInit = tasks.length > 0 && tasks.every(function(name) {
+ var obj = task._taskPlusArgs(name).task;
+ return obj && obj.init;
+ });
+
+ // Get any local Gruntfile or tasks that might exist. Use --gruntfile override
+ // if specified, otherwise search the current directory or any parent.
+ var gruntfile, msg;
+ if (allInit || options.gruntfile === false) {
+ gruntfile = null;
+ } else {
+ gruntfile = grunt.option('gruntfile') ||
+ grunt.file.findup('Gruntfile.{js,coffee}', {nocase: true});
+ msg = 'Reading "' + (gruntfile ? path.basename(gruntfile) : '???') + '" Gruntfile...';
+ }
+
+ if (options.gruntfile === false) {
+ // Grunt was run as a lib with {gruntfile: false}.
+ } else if (gruntfile && grunt.file.exists(gruntfile)) {
+ grunt.verbose.writeln().write(msg).ok();
+ // Change working directory so that all paths are relative to the
+ // Gruntfile's location (or the --base option, if specified).
+ process.chdir(grunt.option('base') || path.dirname(gruntfile));
+ // Load local tasks, if the file exists.
+ loadTasksMessage('Gruntfile');
+ loadTask(gruntfile);
+ } else if (options.help || allInit) {
+ // Don't complain about missing Gruntfile.
+ } else if (grunt.option('gruntfile')) {
+ // If --config override was specified and it doesn't exist, complain.
+ grunt.log.writeln().write(msg).error();
+ grunt.fatal('Unable to find "' + gruntfile + '" Gruntfile.', grunt.fail.code.MISSING_GRUNTFILE);
+ } else if (!grunt.option('help')) {
+ grunt.verbose.writeln().write(msg).error();
+ 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);
+ }
+
+ // Load all user-specified --npm tasks.
+ (grunt.option('npm') || []).map(String).forEach(task.loadNpmTasks);
+ // Load all user-specified --tasks.
+ (grunt.option('tasks') || []).map(String).forEach(task.loadTasks);
+};
diff --git a/node_modules/grunt/lib/grunt/template.js b/node_modules/grunt/lib/grunt/template.js
new file mode 100644
index 0000000..15e1fe1
--- /dev/null
+++ b/node_modules/grunt/lib/grunt/template.js
@@ -0,0 +1,90 @@
+'use strict';
+
+var grunt = require('../grunt');
+
+// The module to be exported.
+var template = module.exports = {};
+
+// External libs.
+template.date = require('dateformat');
+
+// Format today's date.
+template.today = function(format) {
+ var now = new Date();
+ if (process.env.SOURCE_DATE_EPOCH) {
+ now = new Date((process.env.SOURCE_DATE_EPOCH * 1000) + (now.getTimezoneOffset() * 60000));
+ }
+ return template.date(now, format);
+};
+
+// Template delimiters.
+var allDelimiters = {};
+
+// Initialize template delimiters.
+template.addDelimiters = function(name, opener, closer) {
+ var delimiters = allDelimiters[name] = {};
+ // Used by grunt.
+ delimiters.opener = opener;
+ delimiters.closer = closer;
+ // Generate RegExp patterns dynamically.
+ var a = delimiters.opener.replace(/(.)/g, '\\$1');
+ var b = '([\\s\\S]+?)' + delimiters.closer.replace(/(.)/g, '\\$1');
+ // Used by Lo-Dash.
+ delimiters.lodash = {
+ evaluate: new RegExp(a + b, 'g'),
+ interpolate: new RegExp(a + '=' + b, 'g'),
+ escape: new RegExp(a + '-' + b, 'g')
+ };
+};
+
+// The underscore default template syntax should be a pretty sane default for
+// the config system.
+template.addDelimiters('config', '<%', '%>');
+
+// Set Lo-Dash template delimiters.
+template.setDelimiters = function(name) {
+ // Get the appropriate delimiters.
+ var delimiters = allDelimiters[name in allDelimiters ? name : 'config'];
+ // Tell Lo-Dash which delimiters to use.
+ grunt.util._.extend(grunt.util._.templateSettings, delimiters.lodash);
+ // Return the delimiters.
+ return delimiters;
+};
+
+// Process template + data with Lo-Dash.
+template.process = function(tmpl, options) {
+ if (!options) { options = {}; }
+ // Set delimiters, and get a opening match character.
+ var delimiters = template.setDelimiters(options.delimiters);
+ // Clone data, initializing to config data or empty object if omitted.
+ var data = Object.create(options.data || grunt.config.data || {});
+ // Expose grunt so that grunt utilities can be accessed, but only if it
+ // doesn't conflict with an existing .grunt property.
+ if (!('grunt' in data)) { data.grunt = grunt; }
+ // Keep track of last change.
+ var last = tmpl;
+ try {
+ // As long as tmpl contains template tags, render it and get the result,
+ // otherwise just use the template string.
+ while (tmpl.indexOf(delimiters.opener) >= 0) {
+ tmpl = grunt.util._.template(tmpl, options)(data);
+ // Abort if template didn't change - nothing left to process!
+ if (tmpl === last) { break; }
+ last = tmpl;
+ }
+ } catch (e) {
+ // In upgrading to Lo-Dash (or Underscore.js 1.3.3), \n and \r in template
+ // tags now causes an exception to be thrown. Warn the user why this is
+ // happening. https://github.com/documentcloud/underscore/issues/553
+ if (String(e) === 'SyntaxError: Unexpected token ILLEGAL' && /\n|\r/.test(tmpl)) {
+ grunt.log.errorlns('A special character was detected in this template. ' +
+ 'Inside template tags, the \\n and \\r special characters must be ' +
+ 'escaped as \\\\n and \\\\r. (grunt 0.4.0+)');
+ }
+ // Slightly better error message.
+ e.message = 'An error occurred while processing a template (' + e.message + ').';
+ grunt.warn(e, grunt.fail.code.TEMPLATE_ERROR);
+ }
+ // Normalize linefeeds and return.
+ return grunt.util.normalizelf(tmpl);
+};
diff --git a/node_modules/grunt/lib/util/task.js b/node_modules/grunt/lib/util/task.js
new file mode 100644
index 0000000..d39ce1b
--- /dev/null
+++ b/node_modules/grunt/lib/util/task.js
@@ -0,0 +1,335 @@
+(function(exports) {
+
+ 'use strict';
+
+ var grunt = require('../grunt');
+
+ // Construct-o-rama.
+ function Task() {
+ // Information about the currently-running task.
+ this.current = {};
+ // Tasks.
+ this._tasks = {};
+ // Task queue.
+ this._queue = [];
+ // Queue placeholder (for dealing with nested tasks).
+ this._placeholder = {placeholder: true};
+ // Queue marker (for clearing the queue programmatically).
+ this._marker = {marker: true};
+ // Options.
+ this._options = {};
+ // Is the queue running?
+ this._running = false;
+ // Success status of completed tasks.
+ this._success = {};
+ }
+
+ // Expose the constructor function.
+ exports.Task = Task;
+
+ // Create a new Task instance.
+ exports.create = function() {
+ return new Task();
+ };
+
+ // If the task runner is running or an error handler is not defined, throw
+ // an exception. Otherwise, call the error handler directly.
+ Task.prototype._throwIfRunning = function(obj) {
+ if (this._running || !this._options.error) {
+ // Throw an exception that the task runner will catch.
+ throw obj;
+ } else {
+ // Not inside the task runner. Call the error handler and abort.
+ this._options.error.call({name: null}, obj);
+ }
+ };
+
+ // Register a new task.
+ Task.prototype.registerTask = function(name, info, fn) {
+ // If optional "info" string is omitted, shuffle arguments a bit.
+ if (fn == null) {
+ fn = info;
+ info = null;
+ }
+ // String or array of strings was passed instead of fn.
+ var tasks;
+ if (typeof fn !== 'function') {
+ // Array of task names.
+ tasks = this.parseArgs([fn]);
+ // This task function just runs the specified tasks.
+ fn = this.run.bind(this, fn);
+ fn.alias = true;
+ // Generate an info string if one wasn't explicitly passed.
+ if (!info) {
+ info = 'Alias for "' + tasks.join('", "') + '" task' +
+ (tasks.length === 1 ? '' : 's') + '.';
+ }
+ } else if (!info) {
+ info = 'Custom task.';
+ }
+ // Add task into cache.
+ this._tasks[name] = {name: name, info: info, fn: fn};
+ // Make chainable!
+ return this;
+ };
+
+ // Is the specified task an alias?
+ Task.prototype.isTaskAlias = function(name) {
+ return !!this._tasks[name].fn.alias;
+ };
+
+ // Has the specified task been registered?
+ Task.prototype.exists = function(name) {
+ return name in this._tasks;
+ };
+
+ // Rename a task. This might be useful if you want to override the default
+ // behavior of a task, while retaining the old name. This is a billion times
+ // easier to implement than some kind of in-task "super" functionality.
+ Task.prototype.renameTask = function(oldname, newname) {
+ if (!this._tasks[oldname]) {
+ throw new Error('Cannot rename missing "' + oldname + '" task.');
+ }
+ // Rename task.
+ this._tasks[newname] = this._tasks[oldname];
+ // Update name property of task.
+ this._tasks[newname].name = newname;
+ // Remove old name.
+ delete this._tasks[oldname];
+ // Make chainable!
+ return this;
+ };
+
+ // Argument parsing helper. Supports these signatures:
+ // fn('foo') // ['foo']
+ // fn('foo', 'bar', 'baz') // ['foo', 'bar', 'baz']
+ // fn(['foo', 'bar', 'baz']) // ['foo', 'bar', 'baz']
+ Task.prototype.parseArgs = function(args) {
+ // Return the first argument if it's an array, otherwise return an array
+ // of all arguments.
+ return Array.isArray(args[0]) ? args[0] : [].slice.call(args);
+ };
+
+ // Split a colon-delimited string into an array, unescaping (but not
+ // splitting on) any \: escaped colons.
+ Task.prototype.splitArgs = function(str) {
+ if (!str) { return []; }
+ // Store placeholder for \\ followed by \:
+ str = str.replace(/\\\\/g, '\uFFFF').replace(/\\:/g, '\uFFFE');
+ // Split on :
+ return str.split(':').map(function(s) {
+ // Restore place-held : followed by \\
+ return s.replace(/\uFFFE/g, ':').replace(/\uFFFF/g, '\\');
+ });
+ };
+
+ // Given a task name, determine which actual task will be called, and what
+ // arguments will be passed into the task callback. "foo" -> task "foo", no
+ // args. "foo:bar:baz" -> task "foo:bar:baz" with no args (if "foo:bar:baz"
+ // task exists), otherwise task "foo:bar" with arg "baz" (if "foo:bar" task
+ // exists), otherwise task "foo" with args "bar" and "baz".
+ Task.prototype._taskPlusArgs = function(name) {
+ // Get task name / argument parts.
+ var parts = this.splitArgs(name);
+ // Start from the end, not the beginning!
+ var i = parts.length;
+ var task;
+ do {
+ // Get a task.
+ task = this._tasks[parts.slice(0, i).join(':')];
+ // If the task doesn't exist, decrement `i`, and if `i` is greater than
+ // 0, repeat.
+ } while (!task && --i > 0);
+ // Just the args.
+ var args = parts.slice(i);
+ // Maybe you want to use them as flags instead of as positional args?
+ var flags = {};
+ args.forEach(function(arg) { flags[arg] = true; });
+ // The task to run and the args to run it with.
+ return {task: task, nameArgs: name, args: args, flags: flags};
+ };
+
+ // Append things to queue in the correct spot.
+ Task.prototype._push = function(things) {
+ // Get current placeholder index.
+ var index = this._queue.indexOf(this._placeholder);
+ if (index === -1) {
+ // No placeholder, add task+args objects to end of queue.
+ this._queue = this._queue.concat(things);
+ } else {
+ // Placeholder exists, add task+args objects just before placeholder.
+ [].splice.apply(this._queue, [index, 0].concat(things));
+ }
+ };
+
+ // Enqueue a task.
+ Task.prototype.run = function() {
+ // Parse arguments into an array, returning an array of task+args objects.
+ var things = this.parseArgs(arguments).map(this._taskPlusArgs, this);
+ // Throw an exception if any tasks weren't found.
+ var fails = things.filter(function(thing) { return !thing.task; });
+ if (fails.length > 0) {
+ this._throwIfRunning(new Error('Task "' + fails[0].nameArgs + '" not found.'));
+ return this;
+ }
+ // Append things to queue in the correct spot.
+ this._push(things);
+ // Make chainable!
+ return this;
+ };
+
+ // Add a marker to the queue to facilitate clearing it programmatically.
+ Task.prototype.mark = function() {
+ this._push(this._marker);
+ // Make chainable!
+ return this;
+ };
+
+ // Run a task function, handling this.async / return value.
+ Task.prototype.runTaskFn = function(context, fn, done, asyncDone) {
+ // Async flag.
+ var async = false;
+
+ // Update the internal status object and run the next task.
+ var complete = function(success) {
+ var err = null;
+ if (success === false) {
+ // Since false was passed, the task failed generically.
+ err = new Error('Task "' + context.nameArgs + '" failed.');
+ } else if (success instanceof Error || {}.toString.call(success) === '[object Error]') {
+ // An error object was passed, so the task failed specifically.
+ err = success;
+ success = false;
+ } else {
+ // The task succeeded.
+ success = true;
+ }
+ // The task has ended, reset the current task object.
+ this.current = {};
+ // A task has "failed" only if it returns false (async) or if the
+ // function returned by .async is passed false.
+ this._success[context.nameArgs] = success;
+ // If task failed, call error handler.
+ if (!success && this._options.error) {
+ this._options.error.call({name: context.name, nameArgs: context.nameArgs}, err);
+ }
+ // only call done async if explicitly requested to
+ // see: https://github.com/gruntjs/grunt/pull/1026
+ if (asyncDone) {
+ process.nextTick(function() {
+ done(err, success);
+ });
+ } else {
+ done(err, success);
+ }
+ }.bind(this);
+
+ // When called, sets the async flag and returns a function that can
+ // be used to continue processing the queue.
+ context.async = function() {
+ async = true;
+ // The returned function should execute asynchronously in case
+ // someone tries to do this.async()(); inside a task (WTF).
+ return grunt.util._.once(function(success) {
+ setTimeout(function() { complete(success); }, 1);
+ });
+ };
+
+ // Expose some information about the currently-running task.
+ this.current = context;
+
+ try {
+ // Get the current task and run it, setting `this` inside the task
+ // function to be something useful.
+ var success = fn.call(context);
+ // If the async flag wasn't set, process the next task in the queue.
+ if (!async) {
+ complete(success);
+ }
+ } catch (err) {
+ complete(err);
+ }
+ };
+
+ // Begin task queue processing. Ie. run all tasks.
+ Task.prototype.start = function(opts) {
+ if (!opts) {
+ opts = {};
+ }
+ // Abort if already running.
+ if (this._running) { return false; }
+ // Actually process the next task.
+ var nextTask = function() {
+ // Get next task+args object from queue.
+ var thing;
+ // Skip any placeholders or markers.
+ do {
+ thing = this._queue.shift();
+ } while (thing === this._placeholder || thing === this._marker);
+ // If queue was empty, we're all done.
+ if (!thing) {
+ this._running = false;
+ if (this._options.done) {
+ this._options.done();
+ }
+ return;
+ }
+ // Add a placeholder to the front of the queue.
+ this._queue.unshift(this._placeholder);
+
+ // Expose some information about the currently-running task.
+ var context = {
+ // The current task name plus args, as-passed.
+ nameArgs: thing.nameArgs,
+ // The current task name.
+ name: thing.task.name,
+ // The current task arguments.
+ args: thing.args,
+ // The current arguments, available as named flags.
+ flags: thing.flags
+ };
+
+ // Actually run the task function (handling this.async, etc)
+ this.runTaskFn(context, function() {
+ return thing.task.fn.apply(this, this.args);
+ }, nextTask, !!opts.asyncDone);
+
+ }.bind(this);
+
+ // Update flag.
+ this._running = true;
+ // Process the next task.
+ nextTask();
+ };
+
+ // Clear remaining tasks from the queue.
+ Task.prototype.clearQueue = function(options) {
+ if (!options) { options = {}; }
+ if (options.untilMarker) {
+ this._queue.splice(0, this._queue.indexOf(this._marker) + 1);
+ } else {
+ this._queue = [];
+ }
+ // Make chainable!
+ return this;
+ };
+
+ // Test to see if all of the given tasks have succeeded.
+ Task.prototype.requires = function() {
+ this.parseArgs(arguments).forEach(function(name) {
+ var success = this._success[name];
+ if (!success) {
+ throw new Error('Required task "' + name +
+ '" ' + (success === false ? 'failed' : 'must be run first') + '.');
+ }
+ }.bind(this));
+ };
+
+ // Override default options.
+ Task.prototype.options = function(options) {
+ Object.keys(options).forEach(function(name) {
+ this._options[name] = options[name];
+ }.bind(this));
+ };
+
+}(typeof exports === 'object' && exports || this));