'use strict'; var fs = require('fs'); var path = require('path'); var PREFIXES = ['', 'grunt-', 'grunt-contrib-']; var EXTENSIONS = ['.coffee', '.js']; var jit = { pluginsRoot: 'node_modules', mappings: {} }; jit.findUp = function (cwd, iterator) { var result = iterator(cwd); if (result) { return result; } var parent = path.resolve(cwd, '..'); return parent !== cwd ? jit.findUp(parent, iterator) : null; }; jit.findPlugin = function (taskName) { var pluginName, taskPath; // Static Mappings if (this.mappings.hasOwnProperty(taskName)) { pluginName = this.mappings[taskName]; if (pluginName.indexOf('/') >= 0 && pluginName.indexOf('@') !== 0) { taskPath = path.resolve(pluginName); if (fs.existsSync(taskPath)) { return jit.loadPlugin(taskName, taskPath, true); } } else { var dir = path.join(jit.pluginsRoot, pluginName, 'tasks'); taskPath = jit.findUp(path.resolve(), function (cwd) { var findPath = path.join(cwd, dir); return fs.existsSync(findPath) ? findPath : null; }); if (taskPath) { return jit.loadPlugin(pluginName, taskPath); } } } // Custom Tasks if (jit.customTasksDir) { for (var i = EXTENSIONS.length; i--;) { taskPath = path.join(jit.customTasksDir, taskName + EXTENSIONS[i]); if (fs.existsSync(taskPath)) { return jit.loadPlugin(taskName, taskPath, true); } } } // Auto Mappings var dashedName = taskName.replace(/([A-Z])/g, '-$1').replace(/_+/g, '-').toLowerCase(); taskPath = jit.findUp(path.resolve(), function (cwd) { for (var p = PREFIXES.length; p--;) { pluginName = PREFIXES[p] + dashedName; var findPath = path.join(cwd, jit.pluginsRoot, pluginName, 'tasks'); if (fs.existsSync(findPath)) { return findPath; } } }); if (taskPath) { return jit.loadPlugin(pluginName, taskPath); } var log = jit.grunt.log.writeln; log(); log('jit-grunt: Plugin for the "'.yellow + taskName.yellow + '" task not found.'.yellow); log('If you have installed the plugin already, please setting the static mapping.'.yellow); log('See'.yellow, 'https://github.com/shootaroo/jit-grunt#static-mappings'.cyan); log(); }; jit.loadPlugin = function (name, path, isFile) { var grunt = jit.grunt; var _write = grunt.log._write; var _nameArgs = grunt.task.current.nameArgs; grunt.task.current.nameArgs = 'loading ' + name; if (jit.hideHeader) { grunt.log._write = function () {}; } grunt.log.header('Loading "' + name + '" plugin'); grunt.log._write = _write; if (isFile) { var fn = require(path); if (typeof fn === 'function') { fn.call(grunt, grunt); } } else { grunt.loadTasks(path); } grunt.task.current.nameArgs = _nameArgs; }; jit.proxy = function (name) { return { task: { name: name, fn: function () { var thing = jit._taskPlusArgs.call(jit.grunt.task, name); if (!thing.task) { jit.findPlugin(thing.args[0]); thing = jit._taskPlusArgs.call(jit.grunt.task, name); if (!thing.task) { return new Error('Task "' + name + '" failed.'); } } this.nameArgs = thing.nameArgs; this.name = thing.task.name; this.args = thing.args; this.flags = thing.flags; return thing.task.fn.apply(this, this.args); } }, nameArgs: name, args: null, flags: null }; }; module.exports = function factory(grunt, mappings) { if (!jit.grunt) { jit.grunt = grunt; jit.hideHeader = !grunt.option('verbose'); // Override _taskPlusArgs jit._taskPlusArgs = grunt.util.task.Task.prototype._taskPlusArgs; grunt.util.task.Task.prototype._taskPlusArgs = jit.proxy; } for (var key in mappings) { if (mappings.hasOwnProperty(key)) { jit.mappings[key] = mappings[key]; } } return jit; };