Permalink
Browse files

Fixes #323 - brings yeoman in-line with bower and introduces componen…

…t directory syncing with app/scripts/vendor
  • Loading branch information...
1 parent 49c675a commit 3d8fc1aecf2bd53e1440898c27be7c5f0ffdc390 @addyosmani committed Sep 14, 2012
Showing with 92 additions and 76 deletions.
  1. +1 −0 cli/package.json
  2. +91 −76 cli/tasks/bower.js
View
@@ -51,6 +51,7 @@
"coffee-script": "~1.3.3",
"grunt-jasmine-task": "~0.2.2",
"faye-websocket": "~0.4.2",
+ "shelljs":"~0.0.6",
"prompt": "~0.1.12",
"colors": "~0.6.0",
"grunt-mocha": "~0.1.3",
View
@@ -3,6 +3,8 @@ var path = require('path');
var fs = require('fs');
var bower = require('bower');
var template = require('bower/lib/util/template');
+var shelljs = require('shelljs');
+
module.exports = function(grunt) {
@@ -33,17 +35,20 @@ module.exports = function(grunt) {
// figure out the alternate install location, if any
var directory = grunt.config('bower.dir');
- // should we run the yeoman post install step
- var install = args[0] === 'install' && directory;
-
// run
var cb = this.async();
command.line(process.argv)
.on('error', grunt.fatal.bind(grunt.fail))
.on('data', grunt.log.writeln.bind(grunt.log))
- // should probably add other end hooks on commands like uninstall, to
- // also remove from directory
- .on('end', install ? grunt.helper('bower:copy', directory, cb) : cb);
+ .on('end', function(){
+ if(args[0] === 'install' && directory) {
+ grunt.helper('bower:copy', directory, cb);
+ } else if(args[0] === 'uninstall' || args[0] === 'update' && directory) {
+ grunt.helper('bower:sync', directory, cb);
+ } else {
+ cb();
+ }
+ });
});
@@ -70,80 +75,90 @@ module.exports = function(grunt) {
return grunt.fatal('bower:copy helper requires a directory path.');
}
- return function() {
- grunt.helper('bower:log', 'copying to', dir);
-
- var scripts = '';
-
- bower.commands.list({ paths: true })
- .on('error', grunt.fatal.bind(grunt.fail))
- .on('data', function(deps) {
- // should probably emit on `end` in bower's internal
- if(typeof deps === 'string') { return; }
-
- // Handler for RequireJS app config.
- // Wires up the relevant RequireJS paths config when
- // running `yeoman install spine backbone` etc.
-
- // Read in application index
- var basePath = 'app';
- var appIndexPath = path.resolve(basePath + '/index.html');
- var indexBuffer = fs.readFileSync(appIndexPath, 'utf8');
- // parse data-main for require config path
- var hasDataMain = (indexBuffer.match(/data-main=['"]([^'"]+)['"]/));
- // If data-main present..
- if(hasDataMain !== null){
- var requireConfigPath = basePath + '/' + hasDataMain[1];
- // check path contains .js, append if not
- if ( requireConfigPath.indexOf('.js') ) {
- requireConfigPath += '.js';
- }
- // check config file exists
- if(grunt.file.exists(requireConfigPath)){
- // if so..
- // iterate over Bower deps, generating the path string fo config
- Object.keys(deps).forEach(function(dep){
- // Quote key if it contains non a-z chars
- var key = /[^\w]/.test( dep ) ? '\'' + dep + '\'' : dep;
- scripts+= " " + key + ": '../../" + deps[dep].replace('.js','') + "',\n";
- });
-
- // read in the existing data-main config
- var cf = fs.readFileSync(requireConfigPath, 'utf8');
- // replace the existing paths with your new paths
- var html = cf.replace(' paths: {', 'paths: {\n' + scripts);
- // Write the paths to config
- fs.writeFileSync(requireConfigPath, html, 'utf8');
- }
- }
-
- // go through each installed package (via cli.tasks, nopt's remain
- // array), figure out the path from bower dependency tree, and copy
- // to final location
- grunt.cli.tasks.split(':').slice(2).forEach(function(dep) {
- var file = deps[dep];
- if(!file) { return; }
- var ext = path.extname(file);
- var dest = path.join(dir, dep + ext);
- grunt.helper('bower:log', 'copying ' + dep, dest);
- if(!grunt.file.exists(file)) {
- grunt.log.writeln(grunt.helper('bower:template', 'warning-missing', { name: dep }));
- grunt.log.writeln(grunt.helper('bower:template', 'warn', {
- name: file,
- shizzle: 'seems missing. You should bug the author of ' + dep + ' package'
- }));
- return;
- }
-
- grunt.file.copy(file, dest);
+ // Resolve application index
+ var scripts = '';
+ var basePath = 'app';
+ var appIndexPath = path.resolve(path.join(basePath + '/index.html'));
+ var indexBuffer = fs.readFileSync(appIndexPath, 'utf8');
+
+ // parse data-main for require config path
+ var datamain = /data-main=['"]([^'"]+)['"]/;
+
+ // Syncronize the components directory with the vendor directory
+ // if we're not having an rjs setup, go through synchronize step directly
+ if(!datamain.test(indexBuffer)){
+ return grunt.helper('bower:sync', dir, cb);
+ }
+
+ // store the relative filepath of the rjs entry point
+ var filepath = indexBuffer.match(datamain)[1];
+
+ // otherwise, request bower for deps listing and update the relevant config
+ // while going through to synchronize step when done
+ bower.commands.list({ paths: true })
+ .on('error', grunt.fatal.bind(grunt.fail))
+ .on('data', function(deps) {
+ // should probably emit on `end` in bower's internal
+ if(typeof deps === 'string') { return; }
+
+ // Handler for RequireJS app config.
+ // Wires up the relevant RequireJS paths config when
+ // running `yeoman install spine backbone` etc.
+
+ var requireConfigPath = basePath + '/' + filepath;
+
+ // check path contains .js, append if not
+ if ( requireConfigPath.indexOf('.js') ) {
+ requireConfigPath += '.js';
+ }
+
+ // check config file exists
+ var configExists = grunt.file.exists(requireConfigPath);
+ if(configExists) {
+ grunt.helper('bower:log', 'Updating RequireJS config: ' + requireConfigPath);
+ // if so..
+ // iterate over Bower deps, generating the path string fo config
+ Object.keys(deps).forEach(function(dep){
+ // Quote key if it contains non a-z chars
+ var key = /[^\w]/.test( dep ) ? '\'' + dep + '\'' : dep;
+ scripts+= " " + key + ": '../../" + deps[dep].replace('.js','') + "',\n";
});
- cb();
- });
- };
+ // read in the existing data-main config
+ var cf = fs.readFileSync(requireConfigPath, 'utf8');
+ // replace the existing paths with your new paths
+ var html = cf.replace(' paths: {', 'paths: {\n' + scripts);
+
+ // Write the paths to config
+ fs.writeFileSync(requireConfigPath, html, 'utf8');
+ }
+
+ // end the process
+ grunt.helper('bower:sync', dir, cb);
+ });
});
+
+ // Helper to syncronize the Bower components directory with app/scripts/vendor
+ grunt.registerHelper('bower:sync', function(dir, cb) {
+ // Clean the vendor directory then sync with the components directory
+
+ if(typeof cb !== 'function') {
+ return grunt.fatal('bower:sync helper requires a callback.');
+ }
+
+ if(!dir) {
+ return grunt.fatal('bower:sync helper requires a directory path.');
+ }
+
+ shelljs.rm('-rf', dir);
+ shelljs.mkdir('-p', dir);
+ shelljs.cp('-R', 'components/*', dir);
+
+ cb();
+ });
+
// Little grunt helper to access the bower template facility.
//
// - name - a String to define the template name to invoke
@@ -164,4 +179,4 @@ module.exports = function(grunt) {
shizzle: stuff
}));
});
-};
+};

0 comments on commit 3d8fc1a

Please sign in to comment.