'use strict'; // # Globbing // for performance reasons we're only matching one level down: // 'test/spec/{,*/}*.js' // use this if you want to recursively match all subfolders: // 'test/spec/**/*.js' module.exports = function (grunt) { var exec = require('child_process').exec; // Load grunt tasks automatically require('load-grunt-tasks')(grunt); // Time how long tasks take. Can help when optimizing build times require('time-grunt')(grunt); // Define the configuration for all the tasks grunt.initConfig({ compress: { main: { options: { archive: 'archive.zip' }, files: [ {src: ['dist/**/*']} // includes files in path ] } }, // Project settings yeoman: { // configurable paths app: require('./bower.json').appPath || 'app', dist: 'dist' }, // Watches files for changes and runs tasks based on the changed files watch: { js: { files: ['{.tmp,<%= yeoman.app %>}/js/{,*/}*.js'], tasks: ['newer:jshint:all', 'update-control-tower'] }, jsTest: { files: ['test/spec/{,*/}*.js'], tasks: ['newer:jshint:test', 'karma'] }, sass: { files: ['<%= yeoman.app %>/scss/{,*/}*.scss'], tasks: ['compass:dev'] }, html: { files: ['<%= yeoman.app %>/index.html'], livereload: true }, templates: { files: ['<%= yeoman.app %>/templates/**/*.hbs'], tasks: ['handlebars:dev'] }, gruntfile: { files: ['Gruntfile.js'] } }, compass: { dist: { options: { sassDir: '<%= yeoman.app %>/scss', cssDir: '<%= yeoman.dist %>/css', environment: 'production' } }, dev: { options: { sassDir: '<%= yeoman.app %>/scss', cssDir: 'app/css' } } }, // The actual grunt server settings connect: { options: { port: 9000, // Change this from '0.0.0.0' to 'localhost' to limit access from outside. hostname: '0.0.0.0', livereload: true }, test: { options: { port: 9001, base: [ '.tmp', 'test', '<%= yeoman.app %>' ] } }, dist: { options: { base: '<%= yeoman.dist %>' } } }, // Make sure code styles are up to par and there are no obvious mistakes jshint: { options: { jshintrc: '.jshintrc', reporter: require('jshint-stylish') }, all: [ 'Gruntfile.js', '<%= yeoman.app %>/scripts/{,*/}*.js' ], test: { options: { jshintrc: '.jshintrc' }, src: ['test/spec/{,*/}*.js'] } }, // Empties folders to start fresh clean: { dist: { files: [{ dot: true, src: [ '.tmp', '<%= yeoman.dist %>/*', ] }] }, server: ['.tmp', '<%= yeoman.app %>/js/generated'] }, uglify: { dist: { files: [{ expand: true, cwd: '.tmp', src: 'app.min.js', dest: 'dist' }] } }, cssmin: { minify: { expand: true, cwd: '<%= yeoman.app %>/css/', src: ['*.css', '!*.min.css'], dest: '<%= yeoman.dist %>/css/' } }, // The following *-min tasks produce minified files in the dist folder imagemin: { dist: { files: [{ expand: true, cwd: '<%= yeoman.app %>/images', src: '{,*/}*.{png,jpg,jpeg,gif}', dest: '<%= yeoman.dist %>/images' }] } }, svgmin: { dist: { files: [{ expand: true, cwd: '<%= yeoman.app %>/images', src: '{,*/}*.svg', dest: '<%= yeoman.dist %>/images' }] } }, htmlmin: { dist: { options: { // Optional configurations that you can uncomment to use // removeCommentsFromCDATA: true, // collapseBooleanAttributes: true, // removeAttributeQuotes: true, // removeRedundantAttributes: true, // useShortDoctype: true, // removeEmptyAttributes: true, // removeOptionalTags: true*/ }, files: [{ expand: true, cwd: '<%= yeoman.app %>', src: ['*.html', 'templates/*.html'], dest: '<%= yeoman.dist %>' }] } }, // Allow the use of non-minsafe AngularJS files. Automatically makes it // minsafe compatible so Uglify does not destroy the ng references // Replace Google CDN references cdnify: { dist: { html: ['<%= yeoman.dist %>/*.html'] } }, // Copies remaining files to places other tasks can use copy: { dist: { files: [{ expand: true, dot: true, cwd: '<%= yeoman.app %>', dest: '<%= yeoman.dist %>', src: [ '*.{ico,png,txt}', '.htaccess', 'images/{,*/}*.{webp}', 'fonts/*', 'templates/*', 'locales/**/*', 'bower_components/font-awesome/css/font-awesome.min.css', 'bower_components/font-awesome/fonts/*' ] }, { expand: true, cwd: '.tmp/images', dest: '<%= yeoman.dist %>/images', src: [ 'generated/*' ] }] }, styles: { expand: true, cwd: '<%= yeoman.app %>/styles', dest: '.tmp/css/', src: '{,*/}*.css' } }, // Run some tasks in parallel to speed up the build process concurrent: { server: [ 'copy:styles' ], test: [ 'copy:styles' ], dist: [ 'copy:styles', 'imagemin', 'svgmin', 'htmlmin' ] }, requirejs: { compile: { options: { baseUrl: 'app', wrap: true, almond: true, optimize: 'none', mainConfigFile: 'app/js/main.js', out: '.tmp/app.concatenated.js', include: ['js/main'], name: 'bower_components/almond/almond' } } }, concat: { options: { separator: ';', }, dist: { src: [ 'app/bower_components/modernizr/modernizr.js', 'app/bower_components/lodash/dist/lodash.js', 'app/bower_components/jquery/dist/jquery.js', 'app/js/lib/highlightRegex.js', 'app/bower_components/handlebars/handlebars.min.js', 'app/bower_components/typeahead.js/dist/typeahead.bundle.min.js', 'app/bower_components/foundation/js/foundation.js', 'app/bower_components/foundation/js/foundation/foundation.reveal.js', 'app/bower_components/foundation/js/foundation/foundation.offcanvas.js', '.tmp/app.concatenated.js', ], dest: '.tmp/app.min.js', }, }, useminPrepare: { html: 'dist/index.html', options: { dest: 'dist' } }, usemin: { html: 'dist/index.html' }, 'regex-replace': { dist: { src: ['dist/index.html'], actions: [ { name: 'remove-requirejs-from-index', search: 'remove-in-build.*end-remove-in-build', replace: function(match){ return ''; }, flags: 'g' } ] } }, handlebars: { dist: { options: { namespace: 'Pixelated' }, files: { '<%= yeoman.dist %>/js/templates.js': '<%= yeoman.app %>/templates/**/*.hbs' } }, dev: { options: { namespace: 'Pixelated' }, files: { '<%= yeoman.app %>/js/generated/hbs/templates.js': '<%= yeoman.app %>/templates/**/*.hbs' } } }, // Test settings karma: { options: { configFile: 'karma.conf.js' }, ci: { singleRun: true, autoWatch: false, colors: false, reporters: ['junit'] }, single: { singleRun: true, autoWatch: false }, dev: { singleRun: false, browsers: ['PhantomJS'] }, debug: { singleRun: false, browsers: ['Chrome'] } } }); grunt.loadNpmTasks('grunt-contrib-requirejs'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('build', function (target) { if (target === 'dist') { return grunt.task.run(['package', 'dist:keepalive']); } grunt.task.run([ 'clean:server', 'compass:dev', 'handlebars:dev', 'concurrent:server', 'update-control-tower' ]); }); /* grunt.registerTask('watch', function (target) { grunt.task.run([ 'build', 'watch' ]); }); */ grunt.registerTask('test-watch', [ 'clean:server', 'handlebars:dev', 'connect:test', 'karma:dev' ]); grunt.registerTask('debug', [ 'clean:server', 'handlebars:dev', 'connect:test', 'karma:debug' ]); grunt.registerTask('test-ci', [ 'clean:server', 'stopbrowsers', 'handlebars:dev', 'concurrent:test', 'connect:test', 'karma:ci' ]); grunt.registerTask('test', [ 'clean:server', 'handlebars:dev', 'connect:test', 'karma:single' ]); grunt.registerTask('package', [ 'clean:dist', 'useminPrepare', 'compass:dist', 'handlebars:dist', 'concurrent:dist', 'copy:dist', 'cdnify', 'cssmin', 'requirejs', 'concat:dist', 'uglify', 'usemin', 'regex-replace:dist', 'compress' ]); grunt.registerTask('default', [ 'newer:jshint', 'test', 'package' ]); grunt.registerTask('stopbrowsers', function () { ['phantom', 'firefox'].forEach(function (browser) { console.log('killing all ' + browser + ' instances'); exec('pgrep -f "' + browser + '" | xargs kill'); console.log('... done'); }); }); grunt.registerTask('update-control-tower', function () { exec('bash -c "flight-control-tower control-tower.yml && mv control_tower.html .tmp/"'); }); };