Advertisement
Guest User

GruntFile

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