1 | var util = require('util');
|
2 | var path = require('path');
|
3 | var spawn = require('child_process').spawn;
|
4 | var compInstall = require('./component_install.js');
|
5 | var fs = require('fs');
|
6 | var _ = require('underscore');
|
7 |
|
8 | var folderMount = function folderMount(connect, point) {
|
9 | return connect.static(path.resolve(point));
|
10 | };
|
11 |
|
12 | var folderDir = function folderDir(connect, point){
|
13 | return connect.directory(path.resolve(point));
|
14 | }
|
15 |
|
16 | var config = require(__dirname + "/config.json");
|
17 | module.exports = function(grunt){
|
18 |
|
19 | var appJsProd = 'app' + Date.now() + ".js";
|
20 | var appCssProd = 'app' + Date.now() + ".css";
|
21 | var indexTemplate = __dirname + '/index.html';
|
22 |
|
23 | var base = grunt.option('targetBase');
|
24 | var cmd = grunt.option('cmd').toString();
|
25 | process.env.targetBase = base;
|
26 |
|
27 | var destination = grunt.option('destination');
|
28 | var serverPath = grunt.option('server');
|
29 |
|
30 |
|
31 | if(grunt.file.exists(base + "/index.html")){
|
32 | indexTemplate = base + "/index.html";
|
33 | }
|
34 |
|
35 |
|
36 | var ignore = ['components','dist','node_modules'];
|
37 | var packageJson = grunt.file.readJSON(base + '/package.json');
|
38 | if(packageJson.compy && packageJson.compy.paths) {
|
39 | ignore = ignore.concat(packageJson.compy.paths);
|
40 | }
|
41 | var ignoreString = '(' + ignore.join('|') + ')';
|
42 |
|
43 |
|
44 |
|
45 | var customTestSetup = (packageJson.compy && packageJson.compy.tests)?packageJson.compy.tests:{};
|
46 | if(customTestSetup.plugins && customTestSetup.plugins.length > 0){
|
47 |
|
48 |
|
49 | customTestSetup.plugins = _(customTestSetup.plugins).map(function(plugin){
|
50 | return base + "/node_modules/" + plugin;
|
51 | });
|
52 | }
|
53 |
|
54 |
|
55 | var compyGruntConfig = {
|
56 | pkg: packageJson,
|
57 | dest: destination,
|
58 | targetBase: base,
|
59 |
|
60 | componentConfig:{
|
61 | name: '<%= pkg.name %>',
|
62 | main: '<%= pkg.compy.main %>',
|
63 | author: '<%= pkg.author %>',
|
64 | description: '<%= pkg.description %>',
|
65 | dependencies: '<%= pkg.compy.dependencies %>',
|
66 | development: '<%= pkg.compy.development %>',
|
67 | version: '<%= pkg.version %>',
|
68 | license: '<%= pkg.license %>',
|
69 | scripts:'<%= src.scripts %>',
|
70 | styles: '<%= src.styles %>',
|
71 | images: '<%= src.images %>',
|
72 | fonts: '<%= src.fonts %>',
|
73 | templates: '<%= src.templates %>',
|
74 | paths: '<%= pkg.compy.paths %>',
|
75 | local: '<%= pkg.compy.local %>',
|
76 | remotes: '<%= pkg.compy.remotes %>',
|
77 | keywords: '<%= pkg.keywords %>',
|
78 | repo: (function(){
|
79 | if(packageJson.repository && packageJson.repository.type === "git"){
|
80 | var repo = /([^\/]*?\/[^\/]*?)\.git/.exec(packageJson.repository.url);
|
81 | return repo && repo[1];
|
82 | }
|
83 | return null;
|
84 | })()
|
85 | },
|
86 |
|
87 | src:{
|
88 | scripts:[ base + '{/!'+ignoreString+'/**/*.js,/*.js}'],
|
89 | styles:[ base + '{/!'+ignoreString+'/**/*.css,/*.css}'],
|
90 | images:[ base+ '/!'+ignoreString+'/**/*.{jpg,png,gif,icn}', base+ '/*.{jpg,png,gif,icn}'],
|
91 | fonts:[ base+ '/!'+ignoreString+'/**/*.{ttf,eof}', base + '/*.{ttf,eof}'],
|
92 | templates: [ base+ '{/!'+ignoreString+'/**/*.html,/*.html}', '!' + base + '/index.html'],
|
93 | tests:[ base + '{/!'+ignoreString+'/**/*.spec.js,/*.spec.js}']
|
94 | },
|
95 |
|
96 | clean: {
|
97 | options:{force:true},
|
98 | dist:['<%= dest %>']
|
99 | },
|
100 |
|
101 | component_constructor:{
|
102 | options:{
|
103 | output:'<%= dest %>',
|
104 | config:'<%= componentConfig %>',
|
105 | base: base,
|
106 | sourceUrls: false
|
107 | },
|
108 | app:{
|
109 | options:{
|
110 | target: 'app',
|
111 | standalone: grunt.option('isStandaloneLib'),
|
112 | configure: function(builder){
|
113 |
|
114 | var pkg = grunt.file.readJSON(base + '/package.json');
|
115 | if(pkg.compy.dependencies){
|
116 | builder.config.dependencies = pkg.compy.dependencies;
|
117 | }
|
118 | ignoreSources(builder.config, grunt.config('src.tests'));
|
119 | usePlugins(base, builder);
|
120 | }
|
121 | }
|
122 | },
|
123 | test: {
|
124 | options:{
|
125 | dev: true,
|
126 | configure: function(builder){
|
127 |
|
128 | var pkg = grunt.file.readJSON(base + '/package.json');
|
129 | if(pkg.compy.dependencies){
|
130 | builder.config.dependencies = pkg.compy.dependencies;
|
131 | }
|
132 | ignoreSources(builder.config);
|
133 | usePlugins(base, builder);
|
134 | }
|
135 | }
|
136 | },
|
137 | styles_dev: {
|
138 | options:{
|
139 | name: 'app',
|
140 | assetType: 'styles',
|
141 | configure: function(builder){
|
142 |
|
143 | var pkg = grunt.file.readJSON(base + '/package.json');
|
144 | if(pkg.compy.dependencies){
|
145 | builder.config.dependencies = pkg.compy.dependencies;
|
146 | }
|
147 | ignoreSources(builder.config);
|
148 | usePlugins(base, builder);
|
149 | }
|
150 | }
|
151 | },
|
152 | scripts_dev: {
|
153 | options:{
|
154 | name: 'app',
|
155 | assetType: 'scripts',
|
156 | configure: function(builder){
|
157 |
|
158 | var pkg = grunt.file.readJSON(base + '/package.json');
|
159 | if(pkg.compy.dependencies){
|
160 | builder.config.dependencies = pkg.compy.dependencies;
|
161 | }
|
162 | ignoreSources(builder.config);
|
163 | usePlugins(base, builder);
|
164 | }
|
165 | }
|
166 | },
|
167 | templates_dev: {
|
168 | options:{
|
169 | name: 'app',
|
170 | assetType: 'templates',
|
171 | configure: function(builder){
|
172 |
|
173 | var pkg = grunt.file.readJSON(base + '/package.json');
|
174 | if(pkg.compy.dependencies){
|
175 | builder.config.dependencies = pkg.compy.dependencies;
|
176 | }
|
177 | ignoreSources(builder.config);
|
178 | usePlugins(base, builder);
|
179 | }
|
180 | }
|
181 | }
|
182 | },
|
183 | watch: {
|
184 | options:{
|
185 | livereload: config.livereloadPort,
|
186 | nospawn: true
|
187 | },
|
188 |
|
189 | js: {
|
190 | files: '<%= src.scripts %>',
|
191 | tasks: ['component_constructor:scripts_dev','concat:dist']
|
192 | },
|
193 | css:{
|
194 | files: '<%= src.styles %>',
|
195 | tasks: ['component_constructor:app', 'concat:dist']
|
196 | },
|
197 | html:{
|
198 | files: '<%= src.templates %>',
|
199 | tasks: ['component_constructor:templates_dev','concat:dist']
|
200 | }
|
201 | },
|
202 | connect: {
|
203 | options: {
|
204 | port: 8080,
|
205 | base: '<%= dest %>',
|
206 | hostname: null,
|
207 | },
|
208 | server:{
|
209 | options: {
|
210 | keepalive: false,
|
211 | middleware: function(connect, options){
|
212 | return [
|
213 | require('connect-livereload')({port:config.livereloadPort}),
|
214 | folderMount(connect, destination),
|
215 | folderDir(connect, destination)]
|
216 | }
|
217 | }
|
218 | },
|
219 | alive:{
|
220 | options: {
|
221 | keepalive: true,
|
222 | }
|
223 | }
|
224 | },
|
225 |
|
226 | preprocess:{
|
227 | html:{
|
228 | options:{
|
229 | context:{
|
230 | name: '<%= pkg.name %>',
|
231 | main: '<%= pkg.compy.main %>',
|
232 | description: '<%= pkg.description %>',
|
233 | title: '<%= pkg.title %>',
|
234 | appdest: 'app.js',
|
235 | appcss: 'app.css'
|
236 | }
|
237 | },
|
238 | src: indexTemplate,
|
239 | dest:'<%= dest %>/index.html'
|
240 | },
|
241 | build:{
|
242 | options:{
|
243 | context:{
|
244 | name: '<%= pkg.name %>',
|
245 | main: '<%= pkg.compy.main %>',
|
246 | description: '<%= pkg.description %>',
|
247 | title: '<%= pkg.title %>',
|
248 | appdest: appJsProd,
|
249 | appcss: appCssProd
|
250 | }
|
251 | },
|
252 | src: indexTemplate,
|
253 | dest:'<%= dest %>/index.html'
|
254 | }
|
255 | },
|
256 |
|
257 | concat: {
|
258 | options:{
|
259 | banner: '<%= pkg.compy.banner %>'
|
260 | },
|
261 | dist: {
|
262 | src: ['<%= dest %>/app.js', __dirname + '/tmpl/runner.js'],
|
263 | dest: '<%= dest%>/app.js'
|
264 | }
|
265 | },
|
266 | uglify: {
|
267 | build: {
|
268 | src: ['<%= dest%>/app.js'],
|
269 | dest: '<%= dest%>/' + appJsProd
|
270 | }
|
271 | },
|
272 | cssmin: {
|
273 | build: {
|
274 | src: ['<%= dest%>/app.css'],
|
275 | dest: '<%= dest%>/' + appCssProd
|
276 | }
|
277 | },
|
278 | karma: {
|
279 | unit: _({
|
280 | autoWatch:false,
|
281 | browsers:["PhantomJS"],
|
282 | colors: true,
|
283 | configFile: __dirname + '/tmpl/karma.config.js',
|
284 | reporters:['dots'],
|
285 | singleRun: true,
|
286 | plugins: [
|
287 | 'karma-phantomjs-launcher',
|
288 | 'karma-chrome-launcher',
|
289 | 'karma-firefox-launcher'
|
290 | ]
|
291 | }).extend(customTestSetup)
|
292 | }
|
293 | }
|
294 | var matchPlugins = require('./component-plugins-matching.js');
|
295 | matchPlugins(compyGruntConfig, getPlugins(base));
|
296 |
|
297 | function usePlugins(baseDir, builder){
|
298 | var plugins = getPlugins(baseDir);
|
299 | plugins.forEach(function(plugin){
|
300 | var pluginModule = require(baseDir + "/node_modules/" + plugin);
|
301 | if(matchPlugins.config[plugin] && matchPlugins.config[plugin].run){
|
302 | return matchPlugins.config[plugin].run(pluginModule, builder);
|
303 | }
|
304 | builder.use(pluginModule);
|
305 | })
|
306 | }
|
307 | |
308 |
|
309 |
|
310 | function getPlugins(baseDir){
|
311 | var componentPlugins = [];
|
312 | if(!fs.existsSync(baseDir + "/node_modules")) return componentPlugins;
|
313 | var nodeModules = fs.readdirSync(baseDir + "/node_modules");
|
314 | nodeModules.forEach(function(module){
|
315 | if(!/^component-/.test(module)) return;
|
316 | componentPlugins.push(module);
|
317 | });
|
318 | return componentPlugins;
|
319 | }
|
320 |
|
321 |
|
322 |
|
323 | if(grunt.file.exists(base + '/Gruntfile.js')){
|
324 | var innerGruntfile = require(base + '/Gruntfile.js');
|
325 | var oldInit = grunt.initConfig;
|
326 | var pseudoGrunt = grunt;
|
327 | pseudoGrunt.initConfig = initConfig;
|
328 | function initConfig(configObject){
|
329 | for(var key in configObject){
|
330 | compyGruntConfig[key] = configObject[key];
|
331 | }
|
332 | oldInit.call(this, compyGruntConfig);
|
333 | }
|
334 | innerGruntfile(pseudoGrunt);
|
335 |
|
336 | var oldReg = grunt.registerTask
|
337 | grunt.registerTask = function(){
|
338 | if(grunt.task._tasks[arguments[0]]) return;
|
339 | oldReg.apply(this, arguments);
|
340 | }
|
341 | }else{
|
342 | grunt.initConfig(compyGruntConfig);
|
343 | }
|
344 | function ignoreSources(config, ignorePatterns){
|
345 | ['images','fonts','scripts','styles','templates'].forEach(function(asset){
|
346 | var testFor = new RegExp('^(' + ignore.join('|') + ')\\/');
|
347 | var ignoreFiles = [];
|
348 | if(ignorePatterns){
|
349 | ignoreFiles = ignoreFiles.concat(grunt.file.expand(ignorePatterns));
|
350 | }
|
351 | var remap = [];
|
352 | if(!config[asset]) return;
|
353 | config[asset].forEach(function(filepath){
|
354 | if(!!~ignoreFiles.indexOf(filepath)) return;
|
355 | var relPath = path.relative(base, filepath);
|
356 | if(testFor.test(relPath)) return;
|
357 | remap.push(relPath.replace(/\\/g,"/"));
|
358 | })
|
359 | config[asset] = remap;
|
360 | })
|
361 | }
|
362 | grunt.config.set('utils.ignoreSources', ignoreSources);
|
363 |
|
364 | if(!!~['build','compile','server','test','watch'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-component-constructor/tasks');
|
365 | if(!!~['server'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-connect/tasks');
|
366 | if(!!~['server','watch'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-watch/tasks');
|
367 | if(!!~['build','compile','test'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-clean/tasks');
|
368 | if(!!~['build','compile'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-preprocess/tasks');
|
369 | if(!!~['build','compile','server'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-concat/tasks');
|
370 | if(!!~['build'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-uglify/tasks');
|
371 | if(!!~['build'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-contrib-cssmin/tasks');
|
372 | if(!!~['test'].indexOf(cmd)) grunt.loadTasks(__dirname + '/node_modules/grunt-karma/tasks');
|
373 |
|
374 |
|
375 | grunt.registerTask('install', 'Install component', function(){
|
376 | var config = grunt.config('componentConfig');
|
377 | ['images','fonts','scripts','styles','templates'].forEach(function(asset){
|
378 | if(config[asset]){
|
379 | config[asset] = grunt.file.expand(config[asset]);
|
380 | }
|
381 | });
|
382 | var done = this.async();
|
383 |
|
384 | ignoreSources(config);
|
385 | var args = [];
|
386 | var pkgCheck = process.argv.slice(-1)[0].split(':');
|
387 | if(pkgCheck.length > 1){
|
388 | pkgCheck.shift();
|
389 | args = args.concat(pkgCheck);
|
390 | }
|
391 | if(!config.dependencies) config.dependencies = {};
|
392 | var dev = grunt.option('devInstall');
|
393 |
|
394 | compInstall(config, {args: args, out: base + "/components", force: grunt.option('force'), dev: dev}, installed);
|
395 |
|
396 | function installed(err, deps){
|
397 | if(args.length === 0) return done();
|
398 | var pkg = grunt.file.readJSON(base + '/package.json');
|
399 | pkg.compy.dependencies = deps;
|
400 | grunt.file.write(base + '/package.json', JSON.stringify(pkg, null, 2));
|
401 | done();
|
402 | }
|
403 | })
|
404 |
|
405 |
|
406 | require('./src/publish.js')(grunt);
|
407 |
|
408 |
|
409 | grunt.registerTask('generate-tests-runner', function(){
|
410 | var specFiles = grunt.config('src.tests');
|
411 | specFiles = grunt.file.expand(specFiles);
|
412 | var source = "";
|
413 | specFiles.forEach(function(file){
|
414 | var runModule = [path.basename(base), path.relative(base, file)].join('/');
|
415 | source += "require('"+runModule+"');\n";
|
416 | });
|
417 | grunt.file.write(path.normalize(base + '/' + grunt.config('dest') + "/runner.js"), source);
|
418 | })
|
419 |
|
420 | grunt.registerTask('server', 'run server', function(arg){
|
421 | if(arg =="watch"){
|
422 | serverPath ? require(serverPath) : grunt.task.run('connect:server');
|
423 | return grunt.task.run('watch');
|
424 | }else{
|
425 | serverPath ? require(serverPath) : grunt.task.run('connect:alive');
|
426 | }
|
427 | });
|
428 |
|
429 | grunt.registerTask('compy-compile', ['clean:dist', 'component_constructor:app','concat:dist','preprocess:html']);
|
430 |
|
431 | grunt.registerTask('compy-build', ['clean:dist', 'component_constructor:app','concat:dist','preprocess:build', 'uglify', 'cssmin']);
|
432 |
|
433 | grunt.registerTask('compy-test', ['clean:dist', 'component_constructor:test','generate-tests-runner' ,'karma'])
|
434 |
|
435 | grunt.registerTask('compile', ['compy-compile']);
|
436 |
|
437 | grunt.registerTask('build', ['compy-build']);
|
438 |
|
439 | grunt.registerTask('test', ['compy-test']);
|
440 |
|
441 | grunt.registerTask('default', ['compile']);
|
442 | }
|
443 |
|