-
-
Notifications
You must be signed in to change notification settings - Fork 734
/
bower.js
185 lines (154 loc) · 6.19 KB
/
bower.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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) {
// Task facade to Twitter Bower.
//
// This task basically just pases our current provess.argv to bower. Special tasks
// like install, list, search etc. are all configured to trigger this one.
//
// A yeoman-specific configuration can be defined in your Gruntfile:
//
// - dir: Alternate directory location. (defaults to: components)
//
// If the dir option is specified, bower is asked for the package dependency
// model and each paths. Each package is then simply copied over the value of
// the dir options.
//
// `components/` next to your Gruntfile is bower's internal directory.
// `app/js/vendor` is your working directory, files used in development and
// concat / min by grunt script.
grunt.registerTask('bower', 'This triggers the `bower` commands.', function() {
// pull in the bower command module
var args = this.args;
var command = bower.commands[args[0]];
if(!command) {
return grunt.fatal('A valid bower command should be specified.');
}
// figure out the alternate install location, if any
var directory = grunt.config('bower.dir');
// run
var cb = this.async();
command.line(process.argv)
.on('error', grunt.fatal.bind(grunt.fail))
.on('data', grunt.log.writeln.bind(grunt.log))
.on('end', function(){
grunt.helper('bower:sync', directory, cb);
/*
if(args[0] === 'install' && directory) {
grunt.helper('bower:sync', directory, cb);
} else if(args[0] === 'uninstall' || args[0] === 'update' && directory) {
grunt.helper('bower:sync', directory, cb);
} else {
cb();
}*/
});
});
// This helper returns a function meant to be used as a direct callback, most
// likely on the end event of a bower command.
//
// Bower's list is used to get the paths of each dependency in
// components/, these deps are simply copied over the directory
// specified.
//
// - dir: directory path to mirror bower's components.
// - cb: callback to call on completion.
//
// Examples:
//
// stuff.on('end', grunt.helper('bower:copy', this.async()));
//
grunt.registerHelper('bower:copy', function(dir, cb) {
if(typeof cb !== 'function') {
return grunt.fatal('bower:copy helper requires a callback.');
}
if(!dir) {
return grunt.fatal('bower:copy helper requires a directory path.');
}
// 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";
});
// 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
// - context - A hash of data to pass through the given template
//
// Returns the template output
grunt.registerHelper('bower:template', function(name, context) {
return template(name, context, true);
});
// Helper to log through bower template action utility.
//
// - name - main message.
// - stuff - additional logging message. Displayed in grey.
grunt.registerHelper('bower:log', function(name, stuff) {
grunt.log.writeln(grunt.helper('bower:template', 'action', {
name: name,
shizzle: stuff
}));
});
};