diff --git a/lib/grunt/task.js b/lib/grunt/task.js index 05893806..2cf733e5 100644 --- a/lib/grunt/task.js +++ b/lib/grunt/task.js @@ -372,6 +372,7 @@ task.loadNpmTasks = function(name) { var root = path.resolve('node_modules'); var pkgpath = path.join(root, name); var pkgfile = path.join(pkgpath, 'package.json'); + var pkgDistDir = ''; // 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)) { @@ -379,9 +380,14 @@ task.loadNpmTasks = function(name) { // 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]); + // Sometimes a module's task are not at the root of the package, the "name" could contain + // the directory to find the tasks (e.g. grunt-foo/dist/tasks). Therefore, if the name + // contains more than two part, then treat the last part as the directory to find the tasks. + if (nameParts.length > 2) { + pkgDistDir = nameParts.slice(2).join('/'); + } 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; @@ -409,11 +415,11 @@ task.loadNpmTasks = function(name) { } // Process task plugins. - var tasksdir = path.join(path.dirname(pkgfile), 'tasks'); + var tasksdir = path.join(path.dirname(pkgfile), pkgDistDir, 'tasks'); if (grunt.file.exists(tasksdir)) { loadTasks(tasksdir); } else { - grunt.log.error('Local Npm module "' + name + '" not found. Is it installed?'); + grunt.log.error('Local Npm module "' + name + '" not found. Is it installed??????'); } };