1 var lrSnippet = require('connect-livereload')();
2 var mountFolder = function (connect, dir) {
3 return connect.static(require('path').resolve(dir));
6 module.exports = function ( grunt ) {
9 * Load required Grunt tasks. These are installed based on the versions listed
10 * in `package.json` when you do `npm install` in this directory.
12 grunt.loadNpmTasks('grunt-contrib-clean');
13 grunt.loadNpmTasks('grunt-contrib-copy');
14 grunt.loadNpmTasks('grunt-contrib-jshint');
15 grunt.loadNpmTasks('grunt-contrib-concat');
16 grunt.loadNpmTasks('grunt-contrib-watch');
17 grunt.loadNpmTasks('grunt-contrib-uglify');
18 grunt.loadNpmTasks('grunt-contrib-coffee');
19 grunt.loadNpmTasks('grunt-conventional-changelog');
20 grunt.loadNpmTasks('grunt-bump');
21 grunt.loadNpmTasks('grunt-coffeelint');
22 //grunt.loadNpmTasks('grunt-recess');
23 grunt.loadNpmTasks('grunt-karma');
24 grunt.loadNpmTasks('grunt-ngmin');
25 grunt.loadNpmTasks('grunt-html2js');
26 grunt.loadNpmTasks('grunt-contrib-less');
27 grunt.loadNpmTasks('grunt-contrib-connect');
28 grunt.loadNpmTasks('grunt-open');
31 * Load in our build configuration file.
33 var userConfig = require( './build.config.js' );
36 * This is the configuration object Grunt uses to give each plugin its
41 * We read in our `package.json` file so we can access the package name and
42 * version. It's already there, so we don't repeat ourselves here.
44 pkg: grunt.file.readJSON("package.json"),
47 * The banner is the comment that is placed at the top of our compiled
48 * source files. It is first processed as a Grunt template, where the `<%=`
49 * pairs are evaluated based on this very configuration object.
54 ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
55 ' * <%= pkg.homepage %>\n' +
57 ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
58 ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' +
63 * Creates a changelog on a new version.
68 template: 'changelog.tpl'
73 * Increments the version number, etc.
82 commitMessage: 'chore(release): v%VERSION%',
88 tagName: 'v%VERSION%',
89 tagMessage: 'Version %VERSION%',
96 * The directories to delete when `grunt clean` is executed.
104 * The `copy` task just copies files from A to B. We use it here to copy
105 * our project assets (images, fonts, etc.) and javascripts into
106 * `build_dir`, and then to copy the assets to `compile_dir`.
113 dest: '<%= build_dir %>/assets/',
119 build_vendor_assets: {
122 src: [ '<%= vendor_files.assets %>' ],
123 dest: '<%= build_dir %>/assets/',
133 src: [ '<%= app_files.js %>' ],
134 dest: '<%= build_dir %>/',
143 src: [ '<%= vendor_files.js %>' ],
144 dest: '<%= build_dir %>/',
150 build_vendorimages: {
153 src: [ '<%= vendor_files.images %>' ],
154 dest: '<%= build_dir %>/',
163 src: [ '<%= vendor_files.css %>' ],
164 dest: '<%= build_dir %>',
174 dest: '<%= compile_dir %>/assets',
175 cwd: '<%= build_dir %>/assets',
181 /* build_vendor_font: {
184 src: [ '<%= vendor_files.font %>' ],
185 dest: '<%= build_dir %>',
196 dest: '<%= compile_dir %>/font',
197 cwd: '<%= build_dir %>/font',
205 * `grunt concat` concatenates multiple source files into a single file.
209 * The `build_css` target concatenates compiled CSS and vendor CSS
214 '<%= vendor_files.css %>',
215 '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
217 dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
220 * The `compile_js` target is the concatenation of our application source
221 * code and all specified vendor source code into a single file.
225 banner: '<%= meta.banner %>'
228 '<%= vendor_files.js %>',
230 '<%= build_dir %>/src/**/*.js',
231 '<%= html2js.common.dest %>',
232 '<%= html2js.app.dest %>',
235 dest: '<%= compile_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.js'
240 * `grunt coffee` compiles the CoffeeScript sources. To work well with the
241 * rest of the build, we have a separate compilation task for sources and
242 * specs so they can go to different places. For example, we need the
243 * sources to live with the rest of the copied JavaScript so we can include
244 * it in the final build, but we don't want to include our specs there.
253 src: [ '<%= app_files.coffee %>' ],
254 dest: '<%= build_dir %>',
260 * `ng-min` annotates the sources before minifying. That is, it allows us
261 * to code without the array syntax.
267 src: [ '<%= app_files.js %>' ],
268 cwd: '<%= build_dir %>',
269 dest: '<%= build_dir %>',
277 * Minify the sources!
282 banner: '<%= meta.banner %>'
285 '<%= concat.compile_js.dest %>': '<%= concat.compile_js.dest %>'
291 * `recess` handles our LESS compilation and uglification automatically.
292 * Only our `main.less` file is included in compilation; all other files
293 * must be imported from this file.
297 src: [ '<%= app_files.less %>' ],
298 dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css',
302 noUnderscores: false,
308 src: [ '<%= recess.build.dest %>' ],
309 dest: '<%= recess.build.dest %>',
313 noUnderscores: false,
321 * `less` less plugin handles the LESS compilation and minification automatically
322 * this has been changed to the LESS plugin from recess plugin above because of
323 * out of memory issues with the original plugin.
329 paths: ["assets/css"],
335 '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.less %>'
340 paths: ["assets/css"],
345 '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': "src/less/main.less"
351 * `jshint` defines the rules of our linter as well as which files we
352 * should check. This file, all javascript sources, and all our unit tests
353 * are linted based on the policies listed in `options`. But we can also
354 * specify exclusionary patterns by prefixing them with an exclamation
355 * point (!); this is useful when code comes from a third party but is
356 * nonetheless inside `src/`.
360 '<%= app_files.js %>'
363 '<%= app_files.jsunit %>'
366 'OriginalGruntfile.js'
381 * `coffeelint` does the same as `jshint`, but for CoffeeScript.
382 * CoffeeScript is not the default in ngBoilerplate, so we're just using
388 src: [ '<%= app_files.coffee %>' ]
393 src: [ '<%= app_files.coffeeunit %>' ]
399 * HTML2JS is a Grunt plugin that takes all of your template files and
400 * places them into JavaScript files as strings that are added to
401 * AngularJS's template cache. This means that the templates too become
402 * part of the initial payload as one JavaScript file. Neat!
406 * These are the templates from `src/app`.
412 src: [ '<%= app_files.atpl %>' ],
413 dest: '<%= build_dir %>/templates-app.js'
417 * These are the templates from `src/common`.
423 src: [ '<%= app_files.ctpl %>' ],
424 dest: '<%= build_dir %>/templates-common.js'
429 * The Karma configurations.
433 configFile: '<%= build_dir %>/karma-unit.js'
438 port: 9877 // IMPORTANT!
446 * The `index` task compiles the `index.html` file as a Grunt template. CSS
447 * and JS files co-exist here but they get split apart later.
452 * During development, we don't want to have wait for compilation,
453 * concatenation, minification, etc. So to avoid these steps, we simply
454 * add all script files directly to the `<head>` of `index.html`. The
455 * `src` property contains the list of included files.
458 dir: '<%= build_dir %>',
460 '<%= vendor_files.js %>',
461 '<%= build_dir %>/src/**/*.js',
462 '<%= html2js.common.dest %>',
463 '<%= html2js.app.dest %>',
464 '<%= vendor_files.css %>',
465 '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
470 * When it is time to have a completely compiled application, we can
471 * alter the above to include only a single JavaScript and a single CSS
472 * file. Now we're back!
475 dir: '<%= compile_dir %>',
477 '<%= concat.compile_js.dest %>',
478 '<%= concat.build_css.dest %>'
479 //'<%= recess.compile.dest %>'
485 * This task compiles the karma template so that changes to its file array
486 * don't have to be managed manually.
490 dir: '<%= build_dir %>',
492 '<%= vendor_files.js %>',
493 '<%= html2js.app.dest %>',
494 '<%= html2js.common.dest %>',
495 '<%= test_files.js %>'
504 middleware: function (connect) {
506 mountFolder(connect, 'build'),
529 path: 'http://127.0.0.1:9000/'
532 path: 'http://127.0.0.1:9001/'
536 * And for rapid development, we have a watch set up that checks to see if
537 * any of the files listed below change, and then to execute the listed
538 * tasks when they do. This just saves us from having to type "grunt" into
539 * the command-line every time we want to see what we're working on; we can
540 * instead just leave "grunt watch" running in a background terminal. Set it
541 * and forget it, as Ron Popeil used to tell us.
543 * But we don't need the same thing to happen for all the files.
547 * By default, we want the Live Reload to work for all tasks; this is
548 * overridden in some tasks (like this file) where browser resources are
549 * unaffected. It runs by default on port 35729, which your browser
550 * plugin should auto-detect.
557 * When the Gruntfile changes, we just want to lint it. In fact, when
558 * your Gruntfile changes, it will automatically be reloaded!
561 files: 'OriginalGruntfile.js',
562 tasks: [ 'jshint:gruntfile' ],
569 * When our JavaScript source files change, we want to run lint them and
570 * run our unit tests.
574 '<%= app_files.js %>'
576 tasks: [ 'jshint:src', 'karma:unit:run', 'copy:build_appjs' ]
580 * When our CoffeeScript source files change, we want to run lint them and
581 * run our unit tests.
585 '<%= app_files.coffee %>'
587 tasks: [ 'coffeelint:src', 'coffee:source', 'karma:unit:run', 'copy:build_appjs' ]
591 * When assets are changed, copy them. Note that this will *not* copy new
592 * files, so this is probably not very useful.
598 tasks: [ 'copy:build_assets' ]
602 * When index.html changes, we need to compile it.
605 files: [ '<%= app_files.html %>' ],
606 tasks: [ 'index:build' ]
610 * When our templates change, we only rewrite the template cache.
614 '<%= app_files.atpl %>',
615 '<%= app_files.ctpl %>'
621 * When the CSS files change, we need to compile and minify them.
624 files: [ 'src/**/*.less' ],
625 tasks: [ 'less:development' ]
629 * When a JavaScript unit test file changes, we only want to lint it and
630 * run the unit tests. We don't want to do any live reloading.
634 '<%= app_files.jsunit %>'
636 tasks: [ 'jshint:test', 'karma:unit:run' ],
643 * When a CoffeeScript unit test file changes, we only want to lint it and
644 * run the unit tests. We don't want to do any live reloading.
648 '<%= app_files.coffeeunit %>'
650 tasks: [ 'coffeelint:test', 'karma:unit:run' ],
658 grunt.initConfig( grunt.util._.extend( taskConfig, userConfig ) );
661 * In order to make it safe to just compile or copy *only* what was changed,
662 * we need to ensure we are starting from a clean, fresh build. So we rename
663 * the `watch` task to `delta` (that's why the configuration var above is
664 * `delta`) and then add a new task called `watch` that does a clean build
665 * before watching for changes.
667 grunt.renameTask( 'watch', 'delta' );
668 grunt.registerTask( 'watch', [ 'build', 'karma:unit', 'delta' ] );
670 grunt.registerTask('live', ['build', 'connect:dev', 'delta']);
672 * The default task is to build and compile.
674 grunt.registerTask( 'default', [ 'build', 'compile' ] );
677 * The `build` task gets your app ready to run for development and testing.
679 grunt.registerTask( 'build', [
680 'clean', 'html2js', 'jshint', 'coffeelint', 'coffee', 'less:development',
681 'concat:build_css', 'copy:build_app_assets', 'copy:build_vendor_assets',
682 'copy:build_appjs', 'copy:build_vendorimages', 'copy:build_vendorjs', 'copy:build_vendorcss', /*'copy:build_vendor_font',*/ 'index:build'/*, 'karmaconfig',
683 'karma:continuous' */
687 * The `compile` task gets your app ready for deployment by concatenating and
688 * minifying your code.
690 grunt.registerTask( 'compile', [
691 'less:development', 'copy:compile_assets', 'ngmin:compile', 'concat:compile_js', 'uglify', 'index:compile'
695 * A utility function to get all app JavaScript sources.
697 function filterForJS ( files ) {
698 return files.filter( function ( file ) {
699 return file.match( /\.js$/ );
704 * A utility function to get all app CSS sources.
706 function filterForCSS ( files ) {
707 return files.filter( function ( file ) {
708 return file.match( /\.css$/ );
713 * The index.html template includes the stylesheet and javascript sources
714 * based on dynamic names calculated in this Gruntfile. This task assembles
715 * the list into variables for the template to use and then runs the
718 grunt.registerMultiTask( 'index', 'Process index.html template', function () {
719 var dirRE = new RegExp( '^('+grunt.config('build_dir')+'|'+grunt.config('compile_dir')+')\/', 'g' );
720 var jsFiles = filterForJS( this.filesSrc ).map( function ( file ) {
721 return file.replace( dirRE, '' );
723 var cssFiles = filterForCSS( this.filesSrc ).map( function ( file ) {
724 return file.replace( dirRE, '' );
727 grunt.file.copy('src/index.html', this.data.dir + '/index.html', {
728 process: function ( contents, path ) {
729 return grunt.template.process( contents, {
733 version: grunt.config( 'pkg.version' )
739 grunt.file.copy('src/login.html', this.data.dir + '/login.html', {
740 process: function ( contents, path ) {
741 return grunt.template.process( contents, {
745 version: grunt.config( 'pkg.version' )
753 * In order to avoid having to specify manually the files needed for karma to
754 * run, we use grunt to manage the list for us. The `karma/*` files are
755 * compiled as grunt templates for use by Karma. Yay!
757 grunt.registerMultiTask( 'karmaconfig', 'Process karma config templates', function () {
758 var jsFiles = filterForJS( this.filesSrc );
760 grunt.file.copy( 'karma/karma-unit.tpl.js', grunt.config( 'build_dir' ) + '/karma-unit.js', {
761 process: function ( contents, path ) {
762 return grunt.template.process( contents, {