1 var lrSnippet = require('connect-livereload')();
2 var mountFolder = function (connect, dir) {
3 return connect.static(require('path').resolve(dir));
6 /*global module:false*/
7 module.exports = function (grunt) {
8 require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
11 * Load in our build configuration file.
13 var userConfig = require( './build.config.js' );
15 // Project configuration.
18 pkg: grunt.file.readJSON('package.json'),
20 banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
21 '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
22 '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
23 '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
24 ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
35 dest: '<%= build_dir %>/assets/',
41 build_vendor_assets: {
44 src: [ '<%= vendor_files.assets %>' ],
45 dest: '<%= build_dir %>/assets/',
55 src: [ '<%= app_files.js %>' ],
56 dest: '<%= build_dir %>/',
65 src: [ '<%= vendor_files.js %>' ],
66 dest: '<%= build_dir %>/',
75 src: [ '<%= vendor_files.css %>' ],
76 dest: '<%= build_dir %>',
85 src: [ '<%= vendor_files.assets %>' ],
86 dest: '<%= build_dir %>',
96 dest: '<%= compile_dir %>/assets',
97 cwd: '<%= build_dir %>/assets',
107 * The `build_css` target concatenates compiled CSS and vendor CSS
112 '<%= vendor_files.css %>',
113 '<%= recess.build.dest %>'
115 dest: '<%= recess.build.dest %>'
118 * The `compile_js` target is the concatenation of our application source
119 * code and all specified vendor source code into a single file.
123 banner: '<%= meta.banner %>'
126 '<%= vendor_files.js %>',
128 '<%= build_dir %>/src/**/*.js',
129 '<%= html2js.app.dest %>',
130 '<%= html2js.common.dest %>',
133 dest: '<%= compile_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.js'
138 * Compile Coffee scripts
147 src: [ '<%= app_files.coffee %>' ],
148 dest: '<%= build_dir %>',
154 * `ng-min` annotates the sources before minifying. That is, it allows us
155 * to code without the array syntax.
161 src: [ '<%= app_files.js %>' ],
162 cwd: '<%= build_dir %>',
163 dest: '<%= build_dir %>',
171 * Minify the sources!
176 banner: '<%= meta.banner %>'
179 '<%= concat.compile_js.dest %>': '<%= concat.compile_js.dest %>'
191 'target/<%= pkg.name %>-combined.css': ['src/css/*.css']
197 * Compile LESS templates to css
201 src: [ '<%= app_files.less %>' ],
202 dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css',
206 noUnderscores: false,
212 src: [ '<%= recess.build.dest %>' ],
213 dest: '<%= recess.build.dest %>',
217 noUnderscores: false,
225 * `jshint` defines the rules of our linter as well as which files we
226 * should check. This file, all javascript sources, and all our unit tests
227 * are linted based on the policies listed in `options`. But we can also
228 * specify exclusionary patterns by prefixing them with an exclamation
229 * point (!); this is useful when code comes from a third party but is
230 * nonetheless inside `src/`.
234 '<%= app_files.js %>'
237 '<%= app_files.jsunit %>'
270 src: [ '<%= app_files.coffee %>' ]
275 src: [ '<%= app_files.coffeeunit %>' ]
281 * HTML2JS is a Grunt plugin that takes all of your template files and
282 * places them into JavaScript files as strings that are added to
283 * AngularJS's template cache. This means that the templates too become
284 * part of the initial payload as one JavaScript file. Neat!
288 * These are the templates from `src/app`.
294 src: [ '<%= app_files.atpl %>' ],
295 dest: '<%= build_dir %>/templates-app.js'
299 * These are the templates from `src/common`.
305 src: [ '<%= app_files.ctpl %>' ],
306 dest: '<%= build_dir %>/templates-common.js'
311 * The Karma configurations.
315 configFile: '<%= build_dir %>/karma-unit.js'
327 * The `index` task compiles the `index.html` file as a Grunt template. CSS
328 * and JS files co-exist here but they get split apart later.
333 * During development, we don't want to have wait for compilation,
334 * concatenation, minification, etc. So to avoid these steps, we simply
335 * add all script files directly to the `<head>` of `index.html`. The
336 * `src` property contains the list of included files.
339 dir: '<%= build_dir %>',
341 '<%= vendor_files.js %>',
342 '<%= build_dir %>/src/**/*.js',
343 '<%= html2js.common.dest %>',
344 '<%= html2js.app.dest %>',
345 '<%= vendor_files.css %>',
346 '<%= recess.build.dest %>'
351 * When it is time to have a completely compiled application, we can
352 * alter the above to include only a single JavaScript and a single CSS
353 * file. Now we're back!
356 dir: '<%= compile_dir %>',
358 '<%= concat.compile_js.dest %>',
359 '<%= vendor_files.css %>',
360 '<%= recess.compile.dest %>'
366 * This task compiles the karma template so that changes to its file array
367 * don't have to be managed manually.
371 dir: '<%= build_dir %>',
373 '<%= vendor_files.js %>',
374 '<%= html2js.app.dest %>',
375 '<%= html2js.common.dest %>',
376 '<%= test_files.js %>'
386 middleware: function (connect) {
388 mountFolder(connect, 'build'),
411 path: 'http://127.0.0.1:9000/'
414 path: 'http://127.0.0.1:9001/'
419 * By default, we want the Live Reload to work for all tasks; this is
420 * overridden in some tasks (like this file) where browser resources are
421 * unaffected. It runs by default on port 35729, which your browser
422 * plugin should auto-detect.
429 * When the Gruntfile changes, we just want to lint it. In fact, when
430 * your Gruntfile changes, it will automatically be reloaded!
433 files: 'Gruntfile.js',
434 tasks: [ 'jshint:gruntfile' ],
441 * When our JavaScript source files change, we want to run lint them and
442 * run our unit tests.
446 '<%= app_files.js %>'
455 * When assets are changed, copy them. Note that this will *not* copy new
456 * files, so this is probably not very useful.
462 tasks: [ 'copy:build_assets' ]
466 * When index.html changes, we need to compile it.
469 files: [ '<%= app_files.html %>' ],
470 tasks: [ 'index:build' ]
474 * When our templates change, we only rewrite the template cache.
478 '<%= app_files.atpl %>',
479 '<%= app_files.ctpl %>'
485 * When the CSS files change, we need to compile and minify them.
488 files: [ 'src/**/*.less' ],
489 tasks: [ 'build_styles' ]
493 * When a JavaScript unit test file changes, we only want to lint it and
494 * run the unit tests. We don't want to do any live reloading.
498 '<%= app_files.jsunit %>'
509 * When a CoffeeScript unit test file changes, we only want to lint it and
510 * run the unit tests. We don't want to do any live reloading.
514 '<%= app_files.coffeeunit %>'
526 grunt.initConfig( grunt.util._.extend( taskConfig, userConfig ) );
529 * In order to make it safe to just compile or copy *only* what was changed,
530 * we need to ensure we are starting from a clean, fresh build. So we rename
531 * the `watch` task to `delta` (that's why the configuration var above is
532 * `delta`) and then add a new task called `watch` that does a clean build
533 * before watching for changes.
535 grunt.renameTask( 'watch', 'delta' );
536 grunt.registerTask('watch', [ 'build', 'delta' ] );
538 // task to do both vendor less compile and css concat.
539 grunt.registerTask('build_styles', ['recess:build', 'concat:build_css']);
541 grunt.registerTask('live', ['build', 'connect:dev', 'open:dev', 'delta']);
544 * The default task is to build and compile.
546 grunt.registerTask( 'default', [ 'build', 'compile' ] );
549 * The `build` task gets your app ready to run for development and testing.
551 grunt.registerTask( 'build', [
552 'clean', 'html2js', 'coffeelint', 'coffee', 'build_styles',
553 'copy:build_app_assets', 'copy:build_vendor_assets',
554 'copy:build_appjs', 'copy:build_vendorjs', 'index:build'
556 // 'copy:build_assets', 'copy:build_appjs', 'copy:build_vendorjs', 'copy:build_vendorcss', 'copy:build_vendorassets',
560 * The `compile` task gets your app ready for deployment by concatenating and
561 * minifying your code.
563 grunt.registerTask( 'compile', [
564 'recess:compile', 'copy:compile_assets', 'ngmin', 'concat:compile_js', 'uglify', 'index:compile'
568 * A utility function to get all app JavaScript sources.
570 function filterForJS ( files ) {
571 return files.filter( function ( file ) {
572 return file.match( /\.js$/ );
577 * A utility function to get all app CSS sources.
579 function filterForCSS ( files ) {
580 return files.filter( function ( file ) {
581 return file.match( /\.css$/ );
586 * The index.html template includes the stylesheet and javascript sources
587 * based on dynamic names calculated in this Gruntfile. This task assembles
588 * the list into variables for the template to use and then runs the
591 grunt.registerMultiTask( 'index', 'Process index.html template', function () {
592 var dirRE = new RegExp( '^('+grunt.config('build_dir')+'|'+grunt.config('compile_dir')+')\/', 'g' );
593 var jsFiles = filterForJS( this.filesSrc ).map( function ( file ) {
594 return file.replace( dirRE, '' );
596 var cssFiles = filterForCSS( this.filesSrc ).map( function ( file ) {
597 return file.replace( dirRE, '' );
600 grunt.file.copy('src/index.html', this.data.dir + '/index.html', {
601 process: function ( contents, path ) {
602 return grunt.template.process( contents, {
606 version: grunt.config( 'pkg.version' )
614 * In order to avoid having to specify manually the files needed for karma to
615 * run, we use grunt to manage the list for us. The `karma/*` files are
616 * compiled as grunt templates for use by Karma. Yay!
618 grunt.registerMultiTask( 'karmaconfig', 'Process karma config templates', function () {
619 var jsFiles = filterForJS( this.filesSrc );
621 grunt.file.copy( 'karma/karma-unit.tpl.js', grunt.config( 'build_dir' ) + '/karma-unit.js', {
622 process: function ( contents, path ) {
623 return grunt.template.process( contents, {