Merge "Yang Visualizer"
[dlux.git] / dlux-web / Gruntfile.js
1 var lrSnippet = require('connect-livereload')();\r
2 var mountFolder = function (connect, dir) {\r
3     return connect.static(require('path').resolve(dir));\r
4 };\r
5 \r
6 module.exports = function ( grunt ) {\r
7 \r
8   /**\r
9    * Load required Grunt tasks. These are installed based on the versions listed\r
10    * in `package.json` when you do `npm install` in this directory.\r
11    */\r
12   grunt.loadNpmTasks('grunt-contrib-clean');\r
13   grunt.loadNpmTasks('grunt-contrib-copy');\r
14   grunt.loadNpmTasks('grunt-contrib-jshint');\r
15   grunt.loadNpmTasks('grunt-contrib-concat');\r
16   grunt.loadNpmTasks('grunt-contrib-watch');\r
17   grunt.loadNpmTasks('grunt-contrib-uglify');\r
18   grunt.loadNpmTasks('grunt-conventional-changelog');\r
19   grunt.loadNpmTasks('grunt-bump');\r
20   //grunt.loadNpmTasks('grunt-recess');\r
21   grunt.loadNpmTasks('grunt-shell');\r
22   grunt.loadNpmTasks('grunt-karma');\r
23   grunt.loadNpmTasks('grunt-ng-annotate');\r
24   grunt.loadNpmTasks('grunt-html2js');\r
25   grunt.loadNpmTasks('grunt-contrib-less');\r
26   grunt.loadNpmTasks('grunt-contrib-connect');\r
27   grunt.loadNpmTasks('grunt-open');\r
28   grunt.loadNpmTasks('grunt-replace');\r
29 \r
30   /**\r
31    * Load in our build configuration file.\r
32    */\r
33   var userConfig = require( './build.config.js' );\r
34 \r
35   var envConfig = {\r
36 \r
37       replace: {\r
38           development: {\r
39               options: {\r
40                   patterns: [\r
41                       {\r
42                           json: grunt.file.readJSON('./config/development.json')\r
43                       }\r
44                   ]\r
45               },\r
46               files: [\r
47                   {\r
48                       expand: true,\r
49                       flatten: true,\r
50                       src: ['./config/env.module.js'],\r
51                       dest: 'src/common/config/'\r
52                   }\r
53               ]\r
54           },\r
55           production: {\r
56               options: {\r
57                   patterns: [\r
58                       {\r
59                           json: grunt.file.readJSON('./config/production.json')\r
60                       }\r
61                   ]\r
62               },\r
63               files: [\r
64                   {\r
65                       expand: true,\r
66                       flatten: true,\r
67                       src: ['./config/env.module.js'],\r
68                       dest: 'src/common/config/'\r
69                   }\r
70               ]\r
71           }\r
72       }\r
73   }\r
74 \r
75   /**\r
76    * This is the configuration object Grunt uses to give each plugin its\r
77    * instructions.\r
78    */\r
79   var taskConfig = {\r
80     /**\r
81      * We read in our `package.json` file so we can access the package name and\r
82      * version. It's already there, so we don't repeat ourselves here.\r
83      */\r
84     pkg: grunt.file.readJSON("package.json"),\r
85 \r
86     /**\r
87      * The banner is the comment that is placed at the top of our compiled\r
88      * source files. It is first processed as a Grunt template, where the `<%=`\r
89      * pairs are evaluated based on this very configuration object.\r
90      */\r
91     meta: {\r
92       banner:\r
93         '/**\n' +\r
94         ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +\r
95         ' * <%= pkg.homepage %>\n' +\r
96         ' *\n' +\r
97         ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +\r
98         ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' +\r
99         ' */\n'\r
100     },\r
101 \r
102     /**\r
103      * Creates a changelog on a new version.\r
104      */\r
105     changelog: {\r
106       options: {\r
107         dest: 'CHANGELOG.md',\r
108         template: 'changelog.tpl'\r
109       }\r
110     },\r
111 \r
112     /**\r
113      * Increments the version number, etc.\r
114      */\r
115     bump: {\r
116       options: {\r
117         files: [\r
118           "package.json",\r
119           "bower.json"\r
120         ],\r
121         commit: false,\r
122         commitMessage: 'chore(release): v%VERSION%',\r
123         commitFiles: [\r
124           "package.json",\r
125           "client/bower.json"\r
126         ],\r
127         createTag: false,\r
128         tagName: 'v%VERSION%',\r
129         tagMessage: 'Version %VERSION%',\r
130         push: false,\r
131         pushTo: 'origin'\r
132       }\r
133     },\r
134 \r
135     /**\r
136      * The directories to delete when `grunt clean` is executed.\r
137      */\r
138     clean: [\r
139       '<%= build_dir %>',\r
140       '<%= compile_dir %>'\r
141     ],\r
142 \r
143     /**\r
144      * The `copy` task just copies files from A to B. We use it here to copy\r
145      * our project assets (images, fonts, etc.) and javascripts into\r
146      * `build_dir`, and then to copy the assets to `compile_dir`.\r
147      */\r
148     copy: {\r
149       build_app_assets: {\r
150         files: [\r
151           {\r
152             src: [ '**' ],\r
153             dest: '<%= build_dir %>/assets/',\r
154             cwd: 'src/assets',\r
155             expand: true\r
156           }\r
157        ]\r
158       },\r
159       build_vendor_assets: {\r
160         files: [\r
161           {\r
162             src: [ '<%= vendor_files.assets %>' ],\r
163             dest: '<%= build_dir %>/assets/',\r
164             cwd: '.',\r
165             expand: true,\r
166             flatten: true\r
167           }\r
168        ]\r
169       },\r
170       build_appjs: {\r
171         files: [\r
172           {\r
173             src: [ '<%= app_files.js %>' ],\r
174             dest: '<%= build_dir %>/',\r
175             cwd: '.',\r
176             expand: true\r
177           }\r
178         ]\r
179       },\r
180       copy_template: {\r
181         files: [\r
182           {\r
183             src: ['<%= app_files.templates %>'],\r
184             dest: '<%= build_dir %>/',\r
185             cwd: '.',\r
186             expand: true\r
187           }\r
188         ]\r
189       },\r
190       build_vendorjs: {\r
191         files: [\r
192           {\r
193             src: [ '<%= vendor_files.js %>' ],\r
194             dest: '<%= build_dir %>/',\r
195             cwd: '.',\r
196             expand: true\r
197           }\r
198         ]\r
199       },\r
200       build_vendorimages: {\r
201         files: [\r
202           {\r
203             src: [ '<%= vendor_files.images %>' ],\r
204             dest: '<%= build_dir %>/',\r
205             cwd: '.',\r
206             expand: true\r
207           }\r
208         ]\r
209       },\r
210       build_vendorcss: {\r
211         files: [\r
212           {\r
213             src: [ '<%= vendor_files.css %>' ],\r
214             dest: '<%= build_dir %>',\r
215             cwd: '.',\r
216             expand: true\r
217           }\r
218         ]\r
219       },\r
220       compile_assets: {\r
221         files: [\r
222           {\r
223             src: [ '**' ],\r
224             dest: '<%= compile_dir %>/assets',\r
225             cwd: '<%= build_dir %>/assets',\r
226             expand: true\r
227           }\r
228         ]\r
229       },\r
230 \r
231       compile_font: {\r
232         files: [\r
233           {\r
234             src: [ '**' ],\r
235             dest: '<%= compile_dir %>/font',\r
236             cwd: '<%= build_dir %>/font',\r
237             expand: true\r
238           }\r
239         ]\r
240       }\r
241     },\r
242 \r
243     /**\r
244      * `grunt concat` concatenates multiple source files into a single file.\r
245      */\r
246     concat: {\r
247       /**\r
248        * The `build_css` target concatenates compiled CSS and vendor CSS\r
249        * together.\r
250        */\r
251       build_css: {\r
252         src: [\r
253           '<%= vendor_files.css %>',\r
254           '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'\r
255         ],\r
256         dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'\r
257       },\r
258       /**\r
259        * The `compile_js` target is the concatenation of our application source\r
260        * code and all specified vendor source code into a single file.\r
261        */\r
262       compile_js: {\r
263         options: {\r
264           banner: '<%= meta.banner %>'\r
265         },\r
266         src: [\r
267           '<%= vendor_files.js %>',\r
268           'module.prefix',\r
269           '<%= build_dir %>/src/**/*.js',\r
270           '<%= html2js.common.dest %>',\r
271           '<%= html2js.app.dest %>',\r
272           'module.suffix'\r
273         ],\r
274         dest: '<%= compile_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.js'\r
275       }\r
276     },\r
277 \r
278     /**\r
279      * `ng-min` annotates the sources before minifying. That is, it allows us\r
280      * to code without the array syntax.\r
281      */\r
282     ngAnnotate: {\r
283       options: {\r
284         singleQuotes:true\r
285       },\r
286       app: {\r
287         files: [\r
288           {\r
289             src: [ '<%= app_files.js %>' ],\r
290             cwd: '<%= build_dir %>',\r
291             dest: '<%= build_dir %>',\r
292             expand: true\r
293           }\r
294         ]\r
295       }\r
296     },\r
297 \r
298     /**\r
299      * Minify the sources!\r
300      */\r
301     uglify: {\r
302       compile: {\r
303         options: {\r
304           banner: '<%= meta.banner %>'\r
305         },\r
306         files: {\r
307           '<%= concat.compile_js.dest %>': '<%= concat.compile_js.dest %>'\r
308         }\r
309       }\r
310     },\r
311 \r
312       /**\r
313        * `less` less plugin handles the LESS compilation and minification automatically\r
314        * this has been changed to the LESS plugin from recess plugin above because of\r
315        * out of memory issues with the original plugin.\r
316        */\r
317 \r
318       less: {\r
319           development: {\r
320               options: {\r
321                   paths: ["assets/css"],\r
322                   compress: false,\r
323                   syncImport: true,\r
324                   strictImports: true\r
325               },\r
326               files: {\r
327                   '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.less %>'\r
328                   }\r
329           },\r
330           production: {\r
331               options: {\r
332                   paths: ["assets/css"],\r
333                   compress: true,\r
334                   cleancss: true\r
335               },\r
336               files: {\r
337                   '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.less %>'\r
338               }\r
339           }\r
340       },\r
341 \r
342     /**\r
343      * `jshint` defines the rules of our linter as well as which files we\r
344      * should check. This file, all javascript sources, and all our unit tests\r
345      * are linted based on the policies listed in `options`. But we can also\r
346      * specify exclusionary patterns by prefixing them with an exclamation\r
347      * point (!); this is useful when code comes from a third party but is\r
348      * nonetheless inside `src/`.\r
349      */\r
350     jshint: {\r
351       src: [\r
352         '<%= app_files.js %>'\r
353       ],\r
354       test: [\r
355         '<%= app_files.jsunit %>'\r
356       ],\r
357       gruntfile: [\r
358         'OriginalGruntfile.js'\r
359       ],\r
360       options: {\r
361         curly: true,\r
362         immed: true,\r
363         newcap: true,\r
364         noarg: true,\r
365         sub: true,\r
366         boss: true,\r
367         eqnull: true\r
368       },\r
369       globals: {}\r
370     },\r
371 \r
372 \r
373     /**\r
374      * HTML2JS is a Grunt plugin that takes all of your template files and\r
375      * places them into JavaScript files as strings that are added to\r
376      * AngularJS's template cache. This means that the templates too become\r
377      * part of the initial payload as one JavaScript file. Neat!\r
378      */\r
379     html2js: {\r
380       /**\r
381        * These are the templates from `src/app`.\r
382        */\r
383       app: {\r
384         options: {\r
385           base: 'src/app'\r
386         },\r
387         src: [ '<%= app_files.atpl %>' ],\r
388         dest: '<%= build_dir %>/templates-app.js'\r
389       },\r
390 \r
391       /**\r
392        * These are the templates from `src/common`.\r
393        */\r
394       common: {\r
395         options: {\r
396           base: 'src/common'\r
397         },\r
398         src: [ '<%= app_files.ctpl %>' ],\r
399         dest: '<%= build_dir %>/templates-common.js'\r
400       }\r
401     },\r
402 \r
403     /**\r
404      * The Karma configurations.\r
405      */\r
406     karma: {\r
407       options: {\r
408         configFile: '<%= build_dir %>/karma-unit.js'\r
409       },\r
410       unit: {\r
411         runnerPort: 9102,\r
412         background: true,\r
413         port: 9877 // IMPORTANT!\r
414       },\r
415       continuous: {\r
416         singleRun: true,\r
417         browsers: ['PhantomJS']\r
418       }\r
419     },\r
420 \r
421     /**\r
422      * The `index` task compiles the `index.html` file as a Grunt template. CSS\r
423      * and JS files co-exist here but they get split apart later.\r
424      */\r
425     index: {\r
426 \r
427       /**\r
428        * During development, we don't want to have wait for compilation,\r
429        * concatenation, minification, etc. So to avoid these steps, we simply\r
430        * add all script files directly to the `<head>` of `index.html`. The\r
431        * `src` property contains the list of included files.\r
432        */\r
433       build: {\r
434         dir: '<%= build_dir %>',\r
435         src: [\r
436           '<%= html2js.common.dest %>',\r
437           '<%= html2js.app.dest %>',\r
438           '<%= vendor_files.css %>',\r
439           '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'\r
440         ]\r
441       },\r
442 \r
443       /**\r
444        * When it is time to have a completely compiled application, we can\r
445        * alter the above to include only a single JavaScript and a single CSS\r
446        * file. Now we're back!\r
447        */\r
448       compile: {\r
449         dir: '<%= compile_dir %>',\r
450         src: [\r
451           '<%= concat.compile_js.dest %>',\r
452           '<%= concat.build_css.dest %>'\r
453           //'<%= recess.compile.dest %>'\r
454         ]\r
455       }\r
456     },\r
457 \r
458     /**\r
459      * This task compiles the karma template so that changes to its file array\r
460      * don't have to be managed manually.\r
461      */\r
462     karmaconfig: {\r
463       unit: {\r
464         dir: '<%= build_dir %>',\r
465         src: [\r
466           '<%= vendor_files.js %>',\r
467           '<%= html2js.app.dest %>',\r
468           '<%= html2js.common.dest %>',\r
469           '<%= app_files.js_common %>',\r
470           '<%= app_files.js_app %>',\r
471           '<%= app_files.jsunit %>'\r
472         ]\r
473       }\r
474     },\r
475      connect: {\r
476       livereload: {\r
477         options: {\r
478           port: 9000,\r
479           hostname: '0.0.0.0',\r
480           middleware: function (connect) {\r
481             return [\r
482               mountFolder(connect, 'build'),\r
483               lrSnippet\r
484             ];\r
485           }\r
486         }\r
487       },\r
488       dev: {\r
489         options: {\r
490           hostname: '0.0.0.0',\r
491           port: 9000,\r
492           base: 'build'\r
493         }\r
494       },\r
495       prod: {\r
496         options: {\r
497           port: 9001,\r
498           base: 'bin',\r
499           keepalive: true\r
500         }\r
501       }\r
502     },\r
503     open: {\r
504       dev: {\r
505         path: 'http://127.0.0.1:9000/'\r
506       },\r
507       prod: {\r
508         path: 'http://127.0.0.1:9001/'\r
509       }\r
510     },\r
511     /**\r
512      * And for rapid development, we have a watch set up that checks to see if\r
513      * any of the files listed below change, and then to execute the listed\r
514      * tasks when they do. This just saves us from having to type "grunt" into\r
515      * the command-line every time we want to see what we're working on; we can\r
516      * instead just leave "grunt watch" running in a background terminal. Set it\r
517      * and forget it, as Ron Popeil used to tell us.\r
518      *\r
519      * But we don't need the same thing to happen for all the files.\r
520      */\r
521     delta: {\r
522       /**\r
523        * By default, we want the Live Reload to work for all tasks; this is\r
524        * overridden in some tasks (like this file) where browser resources are\r
525        * unaffected. It runs by default on port 35729, which your browser\r
526        * plugin should auto-detect.\r
527        */\r
528       options: {\r
529         livereload: true\r
530       },\r
531 \r
532       /**\r
533        * When the Gruntfile changes, we just want to lint it. In fact, when\r
534        * your Gruntfile changes, it will automatically be reloaded!\r
535        */\r
536       gruntfile: {\r
537         files: 'OriginalGruntfile.js',\r
538         tasks: [ 'jshint:gruntfile' ],\r
539         options: {\r
540           livereload: false\r
541         }\r
542       },\r
543 \r
544       /**\r
545        * When our JavaScript source files change, we want to run lint them and\r
546        * run our unit tests.\r
547        */\r
548       jssrc: {\r
549         files: [\r
550           '<%= app_files.js %>'\r
551         ],\r
552         tasks: [ 'jshint:src', 'karma:unit:run', 'copy:build_appjs' ]\r
553       },\r
554 \r
555       /**\r
556        * When assets are changed, copy them. Note that this will *not* copy new\r
557        * files, so this is probably not very useful.\r
558        */\r
559       assets: {\r
560         files: [\r
561           'src/assets/**/*'\r
562         ],\r
563         tasks: [ 'copy:build_app_assets' ]\r
564       },\r
565 \r
566       /**\r
567        * When index.html changes, we need to compile it.\r
568        */\r
569       html: {\r
570         files: [ '<%= app_files.html %>' ],\r
571         tasks: [ 'index:build' ]\r
572       },\r
573 \r
574       /**\r
575        * When our templates change, we only rewrite the template cache.\r
576        */\r
577       tpls: {\r
578         files: [\r
579           '<%= app_files.atpl %>',\r
580           '<%= app_files.ctpl %>'\r
581         ],\r
582         tasks: [ 'html2js' ]\r
583       },\r
584 \r
585       /**\r
586        * When the CSS files change, we need to compile and minify them.\r
587        */\r
588       less: {\r
589         files: [ 'src/**/*.less' ],\r
590         tasks: [ 'less:development' ]\r
591       },\r
592 \r
593       /**\r
594        * When a JavaScript unit test file changes, we only want to lint it and\r
595        * run the unit tests. We don't want to do any live reloading.\r
596        */\r
597       jsunit: {\r
598         files: [\r
599           '<%= app_files.jsunit %>'\r
600         ],\r
601         tasks: [ 'jshint:test', 'karma:unit:run' ],\r
602         options: {\r
603           livereload: false\r
604         }\r
605       }\r
606     },\r
607     shell : {\r
608       requirejs: {\r
609         command: "node node_modules/requirejs/bin/r.js -o optimize.js"\r
610       }\r
611     }\r
612   };\r
613 \r
614   grunt.initConfig( grunt.util._.extend( taskConfig, userConfig, envConfig ) );\r
615 \r
616   /**\r
617    * In order to make it safe to just compile or copy *only* what was changed,\r
618    * we need to ensure we are starting from a clean, fresh build. So we rename\r
619    * the `watch` task to `delta` (that's why the configuration var above is\r
620    * `delta`) and then add a new task called `watch` that does a clean build\r
621    * before watching for changes.\r
622    */\r
623   grunt.renameTask( 'watch', 'delta' );\r
624   grunt.registerTask( 'watch', [ 'build', 'karma:unit', 'delta' ] );\r
625 \r
626   grunt.registerTask('live', ['build', 'connect:dev', 'delta']);\r
627   /**\r
628    * The default task is to build and compile.\r
629    */\r
630   grunt.registerTask( 'default', [ 'compile' ] );\r
631 \r
632   /**\r
633    * The `build` task gets your app ready to run for development and testing.\r
634    */\r
635   grunt.registerTask( 'common', [\r
636       'clean', 'html2js', 'jshint', 'less:development',\r
637       'concat:build_css', 'copy:build_app_assets', 'copy:build_vendor_assets',\r
638       'copy:build_appjs', 'copy:copy_template', 'copy:build_vendorimages', 'copy:build_vendorjs', 'copy:build_vendorcss', 'karmaconfig', 'index:build'\r
639   ]);\r
640 \r
641   grunt.registerTask( 'build', ['replace:development', 'common', 'karma:continuous']);\r
642 \r
643   /**\r
644    * The `compile` task gets your app ready for deployment by concatenating and\r
645    * minifying your code.\r
646    */\r
647   grunt.registerTask( 'compile', ['replace:production', 'common', 'karma:continuous', 'ngAnnotate', 'shell:requirejs']);\r
648 \r
649   /**\r
650    * A utility function to get all app JavaScript sources.\r
651    */\r
652   function filterForJS ( files ) {\r
653     return files.filter( function ( file ) {\r
654       return file.match( /\.js$/ );\r
655     });\r
656   }\r
657 \r
658   /**\r
659    * A utility function to get all app CSS sources.\r
660    */\r
661   function filterForCSS ( files ) {\r
662     return files.filter( function ( file ) {\r
663       return file.match( /\.css$/ );\r
664     });\r
665   }\r
666 \r
667   /**\r
668    * The index.html template includes the stylesheet and javascript sources\r
669    * based on dynamic names calculated in this Gruntfile. This task assembles\r
670    * the list into variables for the template to use and then runs the\r
671    * compilation.\r
672    */\r
673   grunt.registerMultiTask( 'index', 'Process index.html template', function () {\r
674     var dirRE = new RegExp( '^('+grunt.config('build_dir')+'|'+grunt.config('compile_dir')+')\/', 'g' );\r
675     var jsFiles = filterForJS( this.filesSrc ).map( function ( file ) {\r
676       return file.replace( dirRE, '' );\r
677     });\r
678     var cssFiles = filterForCSS( this.filesSrc ).map( function ( file ) {\r
679       return file.replace( dirRE, '' );\r
680     });\r
681 \r
682     grunt.file.copy('src/index.html', this.data.dir + '/index.html', {\r
683       process: function ( contents, path ) {\r
684         return grunt.template.process( contents, {\r
685           data: {\r
686             scripts: jsFiles,\r
687             styles: cssFiles,\r
688             version: grunt.config( 'pkg.version' )\r
689           }\r
690         });\r
691       }\r
692     });\r
693   });\r
694 \r
695   /**\r
696    * In order to avoid having to specify manually the files needed for karma to\r
697    * run, we use grunt to manage the list for us. The `karma/*` files are\r
698    * compiled as grunt templates for use by Karma. Yay!\r
699    */\r
700   grunt.registerMultiTask( 'karmaconfig', 'Process karma config templates', function () {\r
701     var jsFiles = filterForJS( this.filesSrc );\r
702 \r
703     grunt.file.copy( 'karma/karma-unit.tpl.js', grunt.config( 'build_dir' ) + '/karma-unit.js', {\r
704       process: function ( contents, path ) {\r
705         return grunt.template.process( contents, {\r
706           data: {\r
707             scripts: jsFiles\r
708           }\r
709         });\r
710       }\r
711     });\r
712   });\r
713 \r
714 };\r