<commit_before>'use strict';

var webpackDistConfig = require('./webpack.dist.config.js'),
    webpackDevConfig = require('./webpack.config.js');

module.exports = function (grunt) {

    // Project configuration
    grunt.initConfig({
        // Metadata
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
            '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
            '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
            '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
            ' Licensed <%= props.license %> */\n',
        // Task configuration
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: ['dist/']
                }]
            },
            tmp: ".tmp/",
            test: "test/coverage/"
        },
        copy: {
            dist: {
                files: [
                    {
                        flatten: true,
                        expand: true,
                        src: ['src/*'],
                        dest: 'dist/',
                        filter: 'isFile'
                    }
                ]
            }
        },

        // //编译sass
        // sass: {
        //     dist: {
        //         options: {
        //             style: 'compact'
        //         },
        //         files: [{
        //             expand: true,
        //             cwd: 'src/sass',
        //             src: ['*.scss'],
        //             dest: 'src/css/',
        //             ext: '.css'
        //         }]
        //     }
        // },

        // //校验js
        // jshint: {
        //     beforeconcat: {
        //         src: 'src/js/*.js'
        //     },
        //     afterconcat: {
        //         options: {
        //             asi: true
        //         },
        //         src: 'dist/js/*.js'
        //     }
        // },

        // //合并文件
        // concat: {
        //     css: {
        //         src: ['src/css/*.css'],
        //         dest: '.tmp/css/style.css'
        //     },
        //     js: {
        //         src: ['src/js/*.js'],
        //         dest: '.tmp/js/index.js'
        //     }
        // },

        // //压缩js
        // uglify: {
        //     options: {
        //         banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        //             '<%= grunt.template.today("yyyy-mm-dd") %> */\n'
        //     },
        //     dist: {
        //         src: '.tmp/js/index.js',
        //         dest: 'dist/js/index.min.js'
        //     }
        // },

        // //压缩css
        // cssmin: {
        //     dist: {
        //         src: '.tmp/css/style.css',
        //         dest: 'dist/css/style.min.css'
        //     }
        // },

        // //压缩图片
        // imagemin: {
        //     dynamic: {
        //         files: [{
        //             expand: true,
        //             cwd: 'src/',
        //             src: ['img/**/*.{png,jpg,gif}'],
        //             dest: 'dist/'
        //         }]
        //     }
        // },

        // //md5重命名
        // rev: {
        //     dist: {
        //         files: {
        //             src: [
        //                 'dist/css/{,*/}*.css',
        //                 'dist/js/{,*/}*.js',
        //                 'dist/img/{,*/}*.*',
        //                 'dist/fonts/{,*/}*.*',
        //                 'dist/*.{ico,png}'
        //             ]
        //         }
        //     }
        // },

        // //替换压缩后路径与rev重命名后路径
        // usemin: {
        //     html: 'dist/*.html',
        //     css: 'dist/css/{,*/}*.css',
        //     options: {
        //         blockReplacements: {
        //             css: function(block) {
        //                 return '<link rel="stylesheet" type="text/css" href="'+block.dest+'">';
        //             },
        //             js: function(block) {
        //                 return '<script type="text/javascript" src="'+block.dest+'"></script>';
        //             }
        //         }
        //     }
        // },

        // //压缩html
        // htmlmin: {
        //     dist: {
        //         options: {
        //             collapseBooleanAttributes: true,
        //             collapseWhitespace: true,
        //             conservativeCollapse: true,
        //             removeAttributeQuotes: true,
        //             removeCommentsFromCDATA: true,
        //             removeEmptyAttributes: true
        //         },
        //         files: [{
        //             expand: true,
        //             cwd: 'dist',
        //             src: '{,*/}*.html',
        //             dest: 'dist'
        //         }]
        //     }
        // },

        // //启动web服务
        // connect: {
        //     options: {
        //         port: 9000,
        //         hostname: 'localhost',
        //         open: true,
        //         livereload: 35729
        //     },
        //     test: {
        //         options: {
        //             open: {
        //                 target: 'http://localhost:9000/src'
        //             },
        //             middleware: function(connect, options, middlwares) {
        //                 return [
        //                     require('connect-livereload')({
        //                         hostname:'localhost',
        //                         port:35729
        //                     }),
        //                     require('serve-static')('.'),
        //                     require('serve-index')('.')
        //                 ];
        //             }
        //         }
        //     },
        //     dist: {
        //         options: {
        //             base: 'dist',
        //             livereload: false,
        //             keepalive: true,
        //             hostname: '0.0.0.0'
        //         }
        //     }
        // },
        connect: {
            options: {
                port: 8000
            },

            dist: {
                options: {
                    open: {
                        target: 'http://localhost:<%= connect.options.port %>/'
                    },
                    keepalive: true,
                    middleware: function(connect, options, middlwares) {
                        return [
                            require('serve-static')('dist'),
                            require('serve-index')('dist')
                        ];
                    }
                }
            }
        },

        open: {
            options: {
                delay: 500
            },
            dev: {
                path: 'http://localhost:<%= connect.options.port %>/'
            }
        },

        //启动karma测试
        karma: {
          unit: {
            configFile: 'karma.conf.js'
          }
        },

        webpack: {
            // options: webpackDistConfig,
            dist: webpackDistConfig,
            // dist: {
            //     cache: true
            // }
        },

        'webpack-dev-server': {
            options: {
                webpack: webpackDevConfig,
                port: 8000,
                contentBase: './src',
                publicPath: '/assets/',
                hot: true
            },

            start: {
                 keepalive: true
            }
        },
    });

    // These plugins provide necessary tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    // grunt.loadNpmTasks('grunt-contrib-sass');
    // grunt.loadNpmTasks('grunt-contrib-jshint');
    // grunt.loadNpmTasks('grunt-contrib-concat');
    // grunt.loadNpmTasks('grunt-contrib-uglify');
    // grunt.loadNpmTasks('grunt-contrib-cssmin');
    // grunt.loadNpmTasks('grunt-contrib-imagemin');
    // grunt.loadNpmTasks('grunt-rev');
    // grunt.loadNpmTasks('grunt-usemin');
    // grunt.loadNpmTasks('grunt-contrib-htmlmin');
    // grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-open');
    grunt.loadNpmTasks('grunt-webpack');

    grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist']);
        }

        grunt.task.run([
            'open:dev',
            'webpack-dev-server'
        ]);
    });
    grunt.registerTask('test', ['clean:test','karma']);
    grunt.registerTask('build', ['clean', 'copy', 'webpack']);
    grunt.registerTask('default', []);
};

<commit_msg>modify Gruntfile<commit_after>'use strict';

var webpackDistConfig = require('./webpack.dist.config.js'),
    webpackDevConfig = require('./webpack.config.js');

module.exports = function (grunt) {

    // Project configuration
    grunt.initConfig({
        // Metadata
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
            '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
            '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
            '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
            ' Licensed <%= props.license %> */\n',
        // Task configuration
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: ['dist/']
                }]
            },
            tmp: ".tmp/",
            test: "test/coverage/"
        },
        copy: {
            dist: {
                files: [
                    {
                        flatten: true,
                        expand: true,
                        src: ['src/*'],
                        dest: 'dist/',
                        filter: 'isFile'
                    }
                ]
            }
        },

        // //编译sass
        // sass: {
        //     dist: {
        //         options: {
        //             outputStyle: 'compact'
        //         },
        //         files: [{
        //             expand: true,
        //             cwd: 'src/sass',
        //             src: ['*.scss'],
        //             dest: 'src/css/',
        //             ext: '.css'
        //         }]
        //     }
        // },

        // //校验js
        // jshint: {
        //     beforeconcat: {
        //         src: 'src/js/*.js'
        //     },
        //     afterconcat: {
        //         options: {
        //             asi: true
        //         },
        //         src: 'dist/js/*.js'
        //     }
        // },

        // //合并文件
        // concat: {
        //     css: {
        //         src: ['src/css/*.css'],
        //         dest: '.tmp/css/style.css'
        //     },
        //     js: {
        //         src: ['src/js/*.js'],
        //         dest: '.tmp/js/index.js'
        //     }
        // },

        // //压缩js
        // uglify: {
        //     options: {
        //         banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        //             '<%= grunt.template.today("yyyy-mm-dd") %> */\n'
        //     },
        //     dist: {
        //         src: '.tmp/js/index.js',
        //         dest: 'dist/js/index.min.js'
        //     }
        // },

        // //压缩css
        // cssmin: {
        //     dist: {
        //         src: '.tmp/css/style.css',
        //         dest: 'dist/css/style.min.css'
        //     }
        // },

        // //压缩图片
        // imagemin: {
        //     dynamic: {
        //         files: [{
        //             expand: true,
        //             cwd: 'src/',
        //             src: ['img/**/*.{png,jpg,gif}'],
        //             dest: 'dist/'
        //         }]
        //     }
        // },

        // //md5重命名
        // rev: {
        //     dist: {
        //         files: {
        //             src: [
        //                 'dist/css/{,*/}*.css',
        //                 'dist/js/{,*/}*.js',
        //                 'dist/img/{,*/}*.*',
        //                 'dist/fonts/{,*/}*.*',
        //                 'dist/*.{ico,png}'
        //             ]
        //         }
        //     }
        // },

        // //替换压缩后路径与rev重命名后路径
        // usemin: {
        //     html: 'dist/*.html',
        //     css: 'dist/css/{,*/}*.css',
        //     options: {
        //         blockReplacements: {
        //             css: function(block) {
        //                 return '<link rel="stylesheet" type="text/css" href="'+block.dest+'">';
        //             },
        //             js: function(block) {
        //                 return '<script type="text/javascript" src="'+block.dest+'"></script>';
        //             }
        //         }
        //     }
        // },

        // //压缩html
        // htmlmin: {
        //     dist: {
        //         options: {
        //             collapseBooleanAttributes: true,
        //             collapseWhitespace: true,
        //             conservativeCollapse: true,
        //             removeAttributeQuotes: true,
        //             removeCommentsFromCDATA: true,
        //             removeEmptyAttributes: true
        //         },
        //         files: [{
        //             expand: true,
        //             cwd: 'dist',
        //             src: '{,*/}*.html',
        //             dest: 'dist'
        //         }]
        //     }
        // },

        // //启动web服务
        // connect: {
        //     options: {
        //         port: 9000,
        //         hostname: 'localhost',
        //         open: true,
        //         livereload: 35729
        //     },
        //     test: {
        //         options: {
        //             open: {
        //                 target: 'http://localhost:9000/src'
        //             },
        //             middleware: function(connect, options, middlwares) {
        //                 return [
        //                     require('connect-livereload')({
        //                         hostname:'localhost',
        //                         port:35729
        //                     }),
        //                     require('serve-static')('.'),
        //                     require('serve-index')('.')
        //                 ];
        //             }
        //         }
        //     },
        //     dist: {
        //         options: {
        //             base: 'dist',
        //             livereload: false,
        //             keepalive: true,
        //             hostname: '0.0.0.0'
        //         }
        //     }
        // },
        connect: {
            options: {
                port: 8000
            },

            dist: {
                options: {
                    open: {
                        target: 'http://localhost:<%= connect.options.port %>/'
                    },
                    keepalive: true,
                    middleware: function(connect, options, middlwares) {
                        return [
                            require('serve-static')('dist'),
                            require('serve-index')('dist')
                        ];
                    }
                }
            }
        },

        open: {
            options: {
                delay: 500
            },
            dev: {
                path: 'http://localhost:<%= connect.options.port %>/'
            }
        },

        //启动karma测试
        karma: {
          unit: {
            configFile: 'karma.conf.js'
          }
        },

        webpack: {
            // options: webpackDistConfig,
            dist: webpackDistConfig,
            // dist: {
            //     cache: true
            // }
        },

        'webpack-dev-server': {
            options: {
                webpack: webpackDevConfig,
                port: 8000,
                contentBase: './src',
                publicPath: '/assets/',
                hot: true
            },

            start: {
                 keepalive: true
            }
        },
    });

    // These plugins provide necessary tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    // grunt.loadNpmTasks('grunt-contrib-sass');
    // grunt.loadNpmTasks('grunt-contrib-jshint');
    // grunt.loadNpmTasks('grunt-contrib-concat');
    // grunt.loadNpmTasks('grunt-contrib-uglify');
    // grunt.loadNpmTasks('grunt-contrib-cssmin');
    // grunt.loadNpmTasks('grunt-contrib-imagemin');
    // grunt.loadNpmTasks('grunt-rev');
    // grunt.loadNpmTasks('grunt-usemin');
    // grunt.loadNpmTasks('grunt-contrib-htmlmin');
    // grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-open');
    grunt.loadNpmTasks('grunt-webpack');

    grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist']);
        }

        grunt.task.run([
            'open:dev',
            'webpack-dev-server'
        ]);
    });
    grunt.registerTask('test', ['clean:test','karma']);
    grunt.registerTask('build', ['clean', 'copy', 'webpack']);
    grunt.registerTask('default', []);
};

<|endoftext|>


<commit_before>module.exports = function runGrunt(grunt) {
  var
    pkg = grunt.file.readJSON('package.json'),

    path          = require('path'),
    childProcess  = require('child_process'),

    getCommit = function getCommit() {
      return childProcess.spawnSync('git', ['rev-parse', '--short', 'HEAD^']).stdout.toString().trim();
    },

    createLibCopyObject = function createLibCopyObject(dirs) {
      var
        src   = dirs.slice(),
        dest  = [dirs[dirs.length - 1]];

      src.unshift('node_modules');
      dest.unshift('build', 'development', 'js', 'lib');

      src   = path.join.apply(null, src);
      dest  = path.join.apply(null, dest);

      return {
        'src'   : src,
        'dest'  : dest
      };
    },

    registerTask = function registerTask(taskName, task) {
      grunt.registerTask(taskName, task);
    },

    registerTasks = function registerTasks(tasks) {
      var
        taskName;

      for (taskName in tasks) {
        registerTask(taskName, tasks[taskName]);
      }
    },

    getTaskConfig = function getTaskConfig() {
      return {
        'browserify' : {
          'build/tmp/js/client.js' : 'src/js/client.js'
        },

        'clean' : {
          'coverage' : 'test/coverage',

          'tmp'         : 'build/tmp',
          'development' : 'build/development',
          'production'  : 'build/production',
          'publish'     : 'publish'
        },

        'concat' : {
          'options': {
            'separator': ';'
          },

          'build/development/js/bundle.js' : [
            'node_modules/requirejs/require.js',
            'build/tmp/js/template.js',
            'build/tmp/js/client.js'
          ],

          'build/production/js/bundle.js' : [
            'node_modules/requirejs/require.js',
            'build/tmp/js/template.js',
            'build/tmp/js/client.js'
          ]
        },

        'copy' : {
          'asset' : {
            'files' : [
              {
                'expand'  : true,
                'cwd'     : 'asset/',
                'src'     : '**/*',
                'dest'    : 'build/development/'
              },

              {
                'expand'  : true,
                'cwd'     : 'asset/',
                'src'     : '**/*',
                'dest'    : 'build/production/'
              }
            ]
          },

          'fa' : {
            'files' : [
              {
                'expand'  : true,
                'cwd'     : 'node_modules/font-awesome/fonts',
                'src'     : '*',
                'dest'    : 'build/development/fonts'
              },

              {
                'expand'  : true,
                'cwd'     : 'node_modules/font-awesome/fonts',
                'src'     : '*',
                'dest'    : 'build/production/fonts'
              }
            ]
          },

          'view' : {
            'expand'  : true,
            'cwd'     : 'src/html/view',
            'src'     : '**/*',
            'dest'    : 'build/development'
          },

          'lib' : {
            'files' : [
              createLibCopyObject(['angular',               'angular.js']),
              createLibCopyObject(['angular-local-storage', 'dist', 'angular-local-storage.js']),
              createLibCopyObject(['angular-mocks',         'angular-mocks.js']),
              createLibCopyObject(['angular-route',         'angular-route.js'])
            ]
          },

          'rmodule' : {
            'expand'  : true,
            'cwd'     : 'src/js/rmodule',
            'src'     : '**/*',
            'dest'    : 'build/development/js/rmodule'
          },

          'publish' : {
            'expand'  : true,
            'cwd'     : 'build/production',
            'src'     : '**/*',
            'dest'    : 'publish'
          }
        },

        'cssmin' : {
          'options': {
            'shorthandCompacting': false,
            'roundingPrecision': -1
          },

          'build/production/css/app.css' : 'build/development/css/app.css'
        },

        'env' : {
          'coverage': {
            'SRC_COVERAGE'    : '../test/coverage/dimodule/instrument/src/js',
            'KARMA_COVERAGE'  : true
          }
        },

        'htmlmin' : {
          'options': {
            'removeComments'      : true,
            'collapseWhitespace'  : true
          },

          'production': {
            'expand'  : true,
            'src'     : ['*.html'],
            'cwd'     : 'src/html/view',
            'dest'    : 'build/production'
          }
        },

        'instrument' : {
          'files' : 'src/js/dimodule/**/*.js',

          'options' : {
            'lazy'      : true,
            'basePath'  : 'test/coverage/dimodule/instrument'
          }
        },

        'jasmine-node' : {
          'options' : {
            'spec_files'  : ['test/spec/dimodule/**/*.spec.js'],
            'random'      : true
          }
        },

        'jscs' : {
          'options' : {
            'disallowTrailingWhitespace'            : true,
            'disallowTrailingComma'                 : true,
            'disallowFunctionDeclarations'          : true,
            'disallowNewlineBeforeBlockStatements'  : true,
            'disallowMixedSpacesAndTabs'            : true,
            'requireDotNotation'                    : true,
            'requireMultipleVarDecl'                : true,
            'requireSpaceAfterKeywords'             : true,
            'requireSpaceBeforeBlockStatements'     : true,
            'requireSpacesInConditionalExpression'  : true,
            'requireCurlyBraces'                    : true,
            'disallowKeywordsOnNewLine'             : ['else'],
            'validateIndentation'                   : 2,
            'requireSpacesInFunction' : {
              'beforeOpeningCurlyBrace' : true
            }
          },

          'default' : ['*.js', 'config', 'src', 'test/spec']
        },

        'jshint' : {
          'options': {
            'globals'     : {
              'browser'     : false,
              'by'          : false,
              'define'      : false,
              'element'     : false,
              'inject'      : false,
              'protractor'  : false,
              'requirejs'   : false
            },

            'jasmine'     : true,
            'browser'     : true,
            'curly'       : true,
            'eqeqeq'      : true,
            'eqnull'      : true,
            'latedef'     : true,
            'newcap'      : true,
            'node'        : true,
            'nonew'       : true,
            'nonbsp'      : true,
            'quotmark'    : 'single',
            'undef'       : true,
            'debug'       : true,
            'indent'      : 2
          },

          'default' : ['*.js', 'config', 'src', 'test/spec'],

          'strict' : {
            'options' : {
              'noempty' : true,
              'unused'  : 'vars'
            },

            'files' : {
              'src' : ['*.js', 'config', 'src', 'test/spec']
            }
          }
        },

        'karma' : {
          'unit' : {
            'configFile' : 'test/karma.conf.js'
          }
        },

        'makeReport' : {
          'src' : 'test/coverage/**/*.json',

          'options' : {
            'type'  : 'html',
            'dir'   : 'test/coverage/html',
            'print' : 'detail'
          }
        },

        'md5symlink' : {
          'options' : {
            'patterns' : ['.js', '.css']
          },

          'development': {
            //
            // Note: build/development contains lots of other directories.
            //
            'src'   : ['build/development/css/*', 'build/development/js/*'],
            'dest'  : 'build/development'
          },

          'production': {
            'src'   : 'build/production/**/*',
            'dest'  : 'build/production'
          }
        },

        'ngtemplates' : {
          'default' : {
            'cwd'         : 'src/html/template',
            'src'         : '**/*.html',
            'dest'        : 'build/tmp/js/template.js',
            'options'     : {
              'bootstrap': function (module, script) {
                //
                // This predefines a function which will populate the angular
                // cache with the template HTML. Check out the generated
                // template.js under the build directory, you'll need to call
                // it with your angular app instance.
                //
                return 'window.angularTemplates = function angularTemplates(app) { app.run([\'$templateCache\', function ($templateCache) { ' + script + ' } ]) };';
              },

              //
              // Reference existing task.
              //
              'htmlmin' : {
                'collapseWhitespace'        : true,
                'collapseBooleanAttributes' : true
              }
            }
          }
        },

        'notify_hooks' : {
          'options' : {
            'success' : true
          }
        },

        'protractor' : {
          'options' : {
            //
            // This can be disabled after the first run.
            //
            'webdriverManagerUpdate' : true,

            'keepAlive' : true
          },

          'default' : {
            'configFile'  : 'test/protractor.conf.js'
          }
        },

        'replace' : {
          'build' : {
            'options': {
              'patterns': [{
                'json' : {
                  'BUILD_DATE'    : Date.now(),
                  'BUILD_COMMIT'  : getCommit()
                }
              }]
            },

            'files': [{
              'src'   : ['build/tmp/js/client.js'],
              'dest'  : 'build/tmp/js/client.js'
            }]
          },

          'coverage_rmodule': {
            'options': {
              'patterns': [{
                'match'       : /\/[^"]*build\/development/g,
                'replacement' : 'src'
              }]
            },

            'files': [{
              'src'   : ['test/coverage/rmodule/json/coverage.json'],
              'dest'  : 'test/coverage/rmodule/json/coverage.json'
            }]
          },

          'publish' : {
            'options': {
              'patterns': [{
                'match'       : /(href|src)="(css|js)/g,
                'replacement' : function (fullMatch, linkType, folder) {
                  return linkType + '="publish/' + folder;
                }
              }]
            },

            'files': [{
              'src'   : ['publish/index.html'],
              'dest'  : 'publish/index.html'
            }]
          },
        },

        'requirejs' : {
          'production' : {
            'options': {
              'baseUrl'         : 'build/development/js/rmodule',
              //
              // src file is used only as configuration, it is only parsed
              // by requireJS to know what to include. The file which is the
              // source of minification is defined in the `include` property.
              //
              'mainConfigFile'  : 'src/js/client.js',
              'include'         : ['../../../production/js/bundle.js'],
              'out'             : 'build/production/js/bundle.js',

              'uglify2' : {
                'compress' : {
                  'dead_code' : true,

                  //
                  // Put code in your app in a condition
                  // if (DEBUG) ... it will be never built
                  // into the production, however you can
                  // leave it there for development purpose.
                  //
                  'global_defs': {
                    'DEBUG' : false
                  }
                }
              }
            }
          }
        },

        'storeCoverage' : {
          'options' : {
            'include-all-sources' : true,
            'dir'                 : 'test/coverage/dimodule/json'
          }
        },

        'stylus' : {
          'options' : {
            //
            // Use import statements on css as copy inclusion.
            //
            'include css' : true,
            'compress'    : false
          },

          'build/development/css/app.css' : 'src/styl/main.styl'
        },

        'symlinkassets' : {
          'development': {
            'root'  : 'development',
            'src'   : 'build/development/**/*',
            'dest'  : 'build/development'
          },

          'production': {
            'root'  : 'production',
            'src'   : 'build/production/**/*',
            'dest'  : 'build/production'
          }
        },

        'watch' : {
          //
          // Turning off 'spawn' option can speed up the watch execution, however
          // some grunt-task do not play well by having executed multiple times
          // in the same process (e.g. jasmine-node)
          //
          // 'options' : {
          //   'spawn' : false
          // },
          //

          'asset' : {
            'files' : ['asset/**/*'],
            'tasks' : ['copy:asset']
          },

          'bundle' : {
            'files' : ['src/js/client.js', 'src/js/dimodule/**/*.js', 'test/spec/dimodule/**/*.js'],
            'tasks' : ['test:core', 'browserify', 'replace:build', 'concat', 'md5:development', 'test:client']
          },

          'rmodule' : {
            'files' : ['src/js/rmodule/**/*.js', 'test/spec/rmodule/**/*.js'],
            'tasks' : ['test:core', 'copy:rmodule', 'test:client']
          },

          'html' : {
            'files' : ['src/html/**/*.html'],
            'tasks' : ['ngtemplates', 'concat', 'copy:view', 'md5:development']
          },

          'styl' : {
            'files' : ['src/styl/**/*'],
            'tasks' : ['stylus', 'md5:development']
          }
        }
      };
    },

    TASKS = {
      'coverage' : [
        'clean:coverage',
        'env:coverage',
        // 'instrument',
        // 'jasmine-node',
        // 'storeCoverage',
        'karma',
        'replace:coverage_rmodule',
        'makeReport'
      ],

      'test:core' : [
        'jshint:default'
        // 'jasmine-node'
      ],

      'test:style' : [
        'jshint:strict',
        'jscs'
      ],

      'test:client' : [
        'karma'
      ],

      'test:e2e' : [
        'protractor'
      ],

      'md5:development' : [
        'md5symlink:development',
        'symlinkassets:development'
      ],

      'md5:production' : [
        'md5symlink:production',
        'symlinkassets:production'
      ],

      'compile' : [
        'clean:tmp',
        'clean:development',
        'browserify',
        'replace:build',
        'ngtemplates',
        'concat',
        'stylus',
        'copy:fa',
        'copy:lib',
        'copy:rmodule',
        'copy:view',
        'copy:asset',
        'md5:development'
      ],

      'minify' : [
        'clean:production',
        'htmlmin',
        'cssmin',
        'copy:asset',
        'copy:fa',
        'concat',
        'requirejs',
        'md5:production'
      ],

      'build:dev' : [
        'test:core',
        'compile',
        'test:client'
      ],

      'build' : [
        'compile',
        'minify'
      ],

      'test' : [
        'test:core',
        'test:client',
        'test:style'
      ],

      'dev' : [
        'clean',
        'build:dev',
        'watch'
      ],

      'publish' : [
        'clean',
        'build',
        'copy:publish',
        'replace:publish'
      ],

      'default' : [
        'test:style',
        'build',
        'coverage'
      ]
    },

    init = function init() {
      var
        taskConfig = getTaskConfig();

      taskConfig.pkg = pkg;

      grunt.initConfig(taskConfig);

      require('load-grunt-tasks')(grunt);

      // Run notification hooks: notify about successful run also.
      grunt.task.run('notify_hooks');

      registerTasks(TASKS);
    };

  init();
};
<commit_msg>fixup: grunt<commit_after>module.exports = function runGrunt(grunt) {
  var
    pkg = grunt.file.readJSON('package.json'),

    path          = require('path'),
    childProcess  = require('child_process'),

    getCommit = function getCommit() {
      return childProcess.spawnSync('git', ['rev-parse', '--short', 'HEAD^']).stdout.toString().trim();
    },

    createLibCopyObject = function createLibCopyObject(dirs) {
      var
        src   = dirs.slice(),
        dest  = [dirs[dirs.length - 1]];

      src.unshift('node_modules');
      dest.unshift('build', 'development', 'js', 'lib');

      src   = path.join.apply(null, src);
      dest  = path.join.apply(null, dest);

      return {
        'src'   : src,
        'dest'  : dest
      };
    },

    registerTask = function registerTask(taskName, task) {
      grunt.registerTask(taskName, task);
    },

    registerTasks = function registerTasks(tasks) {
      var
        taskName;

      for (taskName in tasks) {
        registerTask(taskName, tasks[taskName]);
      }
    },

    getTaskConfig = function getTaskConfig() {
      return {
        'browserify' : {
          'build/tmp/js/client.js' : 'src/js/client.js'
        },

        'clean' : {
          'coverage' : 'test/coverage',

          'tmp'         : 'build/tmp',
          'development' : 'build/development',
          'production'  : 'build/production',
          'publish'     : 'publish'
        },

        'concat' : {
          'options': {
            'separator': ';'
          },

          'build/development/js/bundle.js' : [
            'node_modules/requirejs/require.js',
            'build/tmp/js/template.js',
            'build/tmp/js/client.js'
          ],

          'build/production/js/bundle.js' : [
            'node_modules/requirejs/require.js',
            'build/tmp/js/template.js',
            'build/tmp/js/client.js'
          ]
        },

        'copy' : {
          'asset' : {
            'files' : [
              {
                'expand'  : true,
                'cwd'     : 'asset/',
                'src'     : '**/*',
                'dest'    : 'build/development/'
              },

              {
                'expand'  : true,
                'cwd'     : 'asset/',
                'src'     : '**/*',
                'dest'    : 'build/production/'
              }
            ]
          },

          'fa' : {
            'files' : [
              {
                'expand'  : true,
                'cwd'     : 'node_modules/font-awesome/fonts',
                'src'     : '*',
                'dest'    : 'build/development/fonts'
              },

              {
                'expand'  : true,
                'cwd'     : 'node_modules/font-awesome/fonts',
                'src'     : '*',
                'dest'    : 'build/production/fonts'
              }
            ]
          },

          'view' : {
            'expand'  : true,
            'cwd'     : 'src/html/view',
            'src'     : '**/*',
            'dest'    : 'build/development'
          },

          'lib' : {
            'files' : [
              createLibCopyObject(['angular',               'angular.js']),
              createLibCopyObject(['angular-local-storage', 'dist', 'angular-local-storage.js']),
              createLibCopyObject(['angular-mocks',         'angular-mocks.js']),
              createLibCopyObject(['angular-route',         'angular-route.js'])
            ]
          },

          'rmodule' : {
            'expand'  : true,
            'cwd'     : 'src/js/rmodule',
            'src'     : '**/*',
            'dest'    : 'build/development/js/rmodule'
          },

          'publish' : {
            'expand'  : true,
            'cwd'     : 'build/production',
            'src'     : '**/*',
            'dest'    : 'publish'
          }
        },

        'cssmin' : {
          'options': {
            'shorthandCompacting': false,
            'roundingPrecision': -1
          },

          'build/production/css/app.css' : 'build/development/css/app.css'
        },

        'env' : {
          'coverage': {
            'SRC_COVERAGE'    : '../test/coverage/dimodule/instrument/src/js',
            'KARMA_COVERAGE'  : true
          }
        },

        'htmlmin' : {
          'options': {
            'removeComments'      : true,
            'collapseWhitespace'  : true
          },

          'production': {
            'expand'  : true,
            'src'     : ['*.html'],
            'cwd'     : 'src/html/view',
            'dest'    : 'build/production'
          }
        },

        'instrument' : {
          'files' : 'src/js/dimodule/**/*.js',

          'options' : {
            'lazy'      : true,
            'basePath'  : 'test/coverage/dimodule/instrument'
          }
        },

        'jasmine-node' : {
          'options' : {
            'spec_files'  : ['test/spec/dimodule/**/*.spec.js'],
            'random'      : true
          }
        },

        'jscs' : {
          'options' : {
            'disallowTrailingWhitespace'            : true,
            'disallowTrailingComma'                 : true,
            'disallowFunctionDeclarations'          : true,
            'disallowNewlineBeforeBlockStatements'  : true,
            'disallowMixedSpacesAndTabs'            : true,
            'requireDotNotation'                    : true,
            'requireMultipleVarDecl'                : true,
            'requireSpaceAfterKeywords'             : true,
            'requireSpaceBeforeBlockStatements'     : true,
            'requireSpacesInConditionalExpression'  : true,
            'requireCurlyBraces'                    : true,
            'disallowKeywordsOnNewLine'             : ['else'],
            'validateIndentation'                   : 2,
            'requireSpacesInFunction' : {
              'beforeOpeningCurlyBrace' : true
            }
          },

          'default' : ['*.js', 'config', 'src', 'test/spec']
        },

        'jshint' : {
          'options': {
            'globals'     : {
              'browser'     : false,
              'by'          : false,
              'define'      : false,
              'element'     : false,
              'inject'      : false,
              'protractor'  : false,
              'requirejs'   : false
            },

            'jasmine'     : true,
            'browser'     : true,
            'curly'       : true,
            'eqeqeq'      : true,
            'eqnull'      : true,
            'latedef'     : true,
            'newcap'      : true,
            'node'        : true,
            'nonew'       : true,
            'nonbsp'      : true,
            'quotmark'    : 'single',
            'undef'       : true,
            'debug'       : true,
            'indent'      : 2
          },

          'default' : ['*.js', 'config', 'src', 'test/spec'],

          'strict' : {
            'options' : {
              'noempty' : true,
              'unused'  : 'vars'
            },

            'files' : {
              'src' : ['*.js', 'config', 'src', 'test/spec']
            }
          }
        },

        'karma' : {
          'unit' : {
            'configFile' : 'test/karma.conf.js'
          }
        },

        'makeReport' : {
          'src' : 'test/coverage/**/*.json',

          'options' : {
            'type'  : 'html',
            'dir'   : 'test/coverage/html',
            'print' : 'detail'
          }
        },

        'md5symlink' : {
          'options' : {
            'patterns' : ['.js', '.css']
          },

          'development': {
            //
            // Note: build/development contains lots of other directories.
            //
            'src'   : ['build/development/css/*', 'build/development/js/*'],
            'dest'  : 'build/development'
          },

          'production': {
            'src'   : 'build/production/**/*',
            'dest'  : 'build/production'
          }
        },

        'ngtemplates' : {
          'default' : {
            'cwd'         : 'src/html/template',
            'src'         : '**/*.html',
            'dest'        : 'build/tmp/js/template.js',
            'options'     : {
              'bootstrap': function (module, script) {
                //
                // This predefines a function which will populate the angular
                // cache with the template HTML. Check out the generated
                // template.js under the build directory, you'll need to call
                // it with your angular app instance.
                //
                return 'window.angularTemplates = function angularTemplates(app) { app.run([\'$templateCache\', function ($templateCache) { ' + script + ' } ]) };';
              },

              //
              // Reference existing task.
              //
              'htmlmin' : {
                'collapseWhitespace'        : true,
                'collapseBooleanAttributes' : true
              }
            }
          }
        },

        'notify_hooks' : {
          'options' : {
            'success' : true
          }
        },

        'protractor' : {
          'options' : {
            //
            // This can be disabled after the first run.
            //
            'webdriverManagerUpdate' : true,

            'keepAlive' : true
          },

          'default' : {
            'configFile'  : 'test/protractor.conf.js'
          }
        },

        'replace' : {
          'build' : {
            'options': {
              'patterns': [{
                'json' : {
                  'BUILD_DATE'    : Date.now(),
                  'BUILD_COMMIT'  : getCommit()
                }
              }]
            },

            'files': [{
              'src'   : ['build/tmp/js/client.js'],
              'dest'  : 'build/tmp/js/client.js'
            }]
          },

          'coverage_rmodule': {
            'options': {
              'patterns': [{
                'match'       : /\/[^"]*build\/development/g,
                'replacement' : 'src'
              }]
            },

            'files': [{
              'src'   : ['test/coverage/rmodule/json/coverage.json'],
              'dest'  : 'test/coverage/rmodule/json/coverage.json'
            }]
          },

          'publish' : {
            'options': {
              'patterns': [{
                'match'       : /(href|src)="(css|js)/g,
                'replacement' : function (fullMatch, linkType, folder) {
                  return linkType + '="publish/' + folder;
                }
              }]
            },

            'files': [{
              'src'   : ['publish/index.html'],
              'dest'  : 'publish/index.html'
            }]
          }
        },

        'requirejs' : {
          'production' : {
            'options': {
              'baseUrl'         : 'build/development/js/rmodule',
              //
              // src file is used only as configuration, it is only parsed
              // by requireJS to know what to include. The file which is the
              // source of minification is defined in the `include` property.
              //
              'mainConfigFile'  : 'src/js/client.js',
              'include'         : ['../../../production/js/bundle.js'],
              'out'             : 'build/production/js/bundle.js',

              'uglify2' : {
                'compress' : {
                  'dead_code' : true,

                  //
                  // Put code in your app in a condition
                  // if (DEBUG) ... it will be never built
                  // into the production, however you can
                  // leave it there for development purpose.
                  //
                  'global_defs': {
                    'DEBUG' : false
                  }
                }
              }
            }
          }
        },

        'storeCoverage' : {
          'options' : {
            'include-all-sources' : true,
            'dir'                 : 'test/coverage/dimodule/json'
          }
        },

        'stylus' : {
          'options' : {
            //
            // Use import statements on css as copy inclusion.
            //
            'include css' : true,
            'compress'    : false
          },

          'build/development/css/app.css' : 'src/styl/main.styl'
        },

        'symlinkassets' : {
          'development': {
            'root'  : 'development',
            'src'   : 'build/development/**/*',
            'dest'  : 'build/development'
          },

          'production': {
            'root'  : 'production',
            'src'   : 'build/production/**/*',
            'dest'  : 'build/production'
          }
        },

        'watch' : {
          //
          // Turning off 'spawn' option can speed up the watch execution, however
          // some grunt-task do not play well by having executed multiple times
          // in the same process (e.g. jasmine-node)
          //
          // 'options' : {
          //   'spawn' : false
          // },
          //

          'asset' : {
            'files' : ['asset/**/*'],
            'tasks' : ['copy:asset']
          },

          'bundle' : {
            'files' : ['src/js/client.js', 'src/js/dimodule/**/*.js', 'test/spec/dimodule/**/*.js'],
            'tasks' : ['test:core', 'browserify', 'replace:build', 'concat', 'md5:development', 'test:client']
          },

          'rmodule' : {
            'files' : ['src/js/rmodule/**/*.js', 'test/spec/rmodule/**/*.js'],
            'tasks' : ['test:core', 'copy:rmodule', 'test:client']
          },

          'html' : {
            'files' : ['src/html/**/*.html'],
            'tasks' : ['ngtemplates', 'concat', 'copy:view', 'md5:development']
          },

          'styl' : {
            'files' : ['src/styl/**/*'],
            'tasks' : ['stylus', 'md5:development']
          }
        }
      };
    },

    TASKS = {
      'coverage' : [
        'clean:coverage',
        'env:coverage',
        // 'instrument',
        // 'jasmine-node',
        // 'storeCoverage',
        'karma',
        'replace:coverage_rmodule',
        'makeReport'
      ],

      'test:core' : [
        'jshint:default'
        // 'jasmine-node'
      ],

      'test:style' : [
        'jshint:strict',
        'jscs'
      ],

      'test:client' : [
        'karma'
      ],

      'test:e2e' : [
        'protractor'
      ],

      'md5:development' : [
        'md5symlink:development',
        'symlinkassets:development'
      ],

      'md5:production' : [
        'md5symlink:production',
        'symlinkassets:production'
      ],

      'compile' : [
        'clean:tmp',
        'clean:development',
        'browserify',
        'replace:build',
        'ngtemplates',
        'concat',
        'stylus',
        'copy:fa',
        'copy:lib',
        'copy:rmodule',
        'copy:view',
        'copy:asset',
        'md5:development'
      ],

      'minify' : [
        'clean:production',
        'htmlmin',
        'cssmin',
        'copy:asset',
        'copy:fa',
        'concat',
        'requirejs',
        'md5:production'
      ],

      'build:dev' : [
        'test:core',
        'compile',
        'test:client'
      ],

      'build' : [
        'compile',
        'minify'
      ],

      'test' : [
        'test:core',
        'test:client',
        'test:style'
      ],

      'dev' : [
        'clean',
        'build:dev',
        'watch'
      ],

      'publish' : [
        'clean',
        'build',
        'copy:publish',
        'replace:publish'
      ],

      'default' : [
        'test:style',
        'build',
        'coverage'
      ]
    },

    init = function init() {
      var
        taskConfig = getTaskConfig();

      taskConfig.pkg = pkg;

      grunt.initConfig(taskConfig);

      require('load-grunt-tasks')(grunt);

      // Run notification hooks: notify about successful run also.
      grunt.task.run('notify_hooks');

      registerTasks(TASKS);
    };

  init();
};
<|endoftext|>


<commit_before>'use strict';
var _ = require('lodash');
var removeMd = require('remove-markdown');

var themeFunctions = require('theme').functions || {};

var MdHelper = require('./elements/MdHelper');
var itemHooks = require('./itemHooks');
var config = require('config');
var siteFunctions = config.functions || {} ;

function allItems() {
  var items = [].concat.apply([], _.keys(config.paths).map(function(sectionName) {
    var section = config.paths[sectionName];

    var paths = parseModules(sectionName, section, section.path());

    var draftPaths = [];
    if(__DEV__ && section.draft) {
      draftPaths = parseModules(sectionName, section, section.draft()).map(function(module) {
        module.isDraft = true;

        return module;
      });
    }

    return (section.sort || defaultSort)(paths.concat(draftPaths));
  }));

  items = itemHooks.preProcessItems(items);
  items = _.map(items, function(o) {
    return processItem(o.file, o.url, o.name, o.sectionName, o.section);
  });
  items = itemHooks.postProcessItems(items);

  // TODO: can this conversion be avoided?
  var ret = {};

  _.each(items, function(o) {
    ret[o.url] = o;
  });

  return ret;
}
exports.allItems = allItems;

function defaultSort(files) {
    return _.sortBy(files, 'date').reverse();
}

function parseModules(sectionName, section, modules) {
  return _.map(modules.keys(), function(name) {
    return {
      name: name.slice(2),
      file: modules(name),
      section: section,
      sectionName: sectionName === '/' ? '' : sectionName,
    };
  });
}

function itemForPath(path) {
  var items = allItems();

  // this check is needed for root paths to work (they have extra slash!)
  return items[path] || items['/' + path];
}
exports.itemForPath = itemForPath;

function renderContent(content) {
  return MdHelper.render(content);
}
exports.renderContent = renderContent;

function processItem(o, url, fileName, sectionName, section) {

  var layout = section.layout;

  var sectionFunctions = section.processItem || {};

  var functions = _.assign({
    date: function(file, fileName, sectionName) {
      return file.date || null;
    },
    content: function(file, fileName, sectionName) {
      return MdHelper.render(file.__content);
    },
    preview: function(file, fileName, sectionName) {
      if (file.preview) {
        return file.preview;
      }
      else {
        var previewLimit = 100;

        if(!file.content) {
          return;
        }

        var stripped = removeMd(file.__content);

        if (stripped.length > previewLimit) {
          return stripped.substr(0, previewLimit) + '…';
        }

        return stripped;
      }
      return file.preview || MdHelper.getContentPreview(file.__content);
    },
    title: function(file, fileName, sectionName) {
      return file.title;
    },
    url: function(file, fileName, sectionName) {
      return sectionName + '/' + fileName.split('.')[0];
    },
    layout: function(file, fileName, sectionName) {
      return layout;
    },
  }, themeFunctions, siteFunctions, sectionFunctions);

  _.forEach(functions, function(fn, name) {
    o[name] = fn(o, fileName, sectionName);
  });

  o.section = sectionName;

  return o;
}
<commit_msg>Set `isDraft` flag for each item<commit_after>'use strict';
var _ = require('lodash');
var removeMd = require('remove-markdown');

var themeFunctions = require('theme').functions || {};

var MdHelper = require('./elements/MdHelper');
var itemHooks = require('./itemHooks');
var config = require('config');
var siteFunctions = config.functions || {} ;

function allItems() {
  var items = [].concat.apply([], _.keys(config.paths).map(function(sectionName) {
    var section = config.paths[sectionName];

    var paths = parseModules(sectionName, section, section.path());

    var draftPaths = [];
    if(__DEV__ && section.draft) {
      draftPaths = parseModules(sectionName, section, section.draft()).map(function(module) {
        module.isDraft = true;

        return module;
      });
    }

    return (section.sort || defaultSort)(paths.concat(draftPaths));
  }));

  items = itemHooks.preProcessItems(items);
  items = _.map(items, function(o) {
    var item = processItem(o.file, o.url, o.name, o.sectionName, o.section);

    item.isDraft = o.isDraft;

    return item;
  });
  items = itemHooks.postProcessItems(items);

  // TODO: can this conversion be avoided?
  var ret = {};

  _.each(items, function(o) {
    ret[o.url] = o;
  });

  return ret;
}
exports.allItems = allItems;

function defaultSort(files) {
    return _.sortBy(files, 'date').reverse();
}

function parseModules(sectionName, section, modules) {
  return _.map(modules.keys(), function(name) {
    return {
      name: name.slice(2),
      file: modules(name),
      section: section,
      sectionName: sectionName === '/' ? '' : sectionName,
    };
  });
}

function itemForPath(path) {
  var items = allItems();

  // this check is needed for root paths to work (they have extra slash!)
  return items[path] || items['/' + path];
}
exports.itemForPath = itemForPath;

function renderContent(content) {
  return MdHelper.render(content);
}
exports.renderContent = renderContent;

function processItem(o, url, fileName, sectionName, section) {

  var layout = section.layout;

  var sectionFunctions = section.processItem || {};

  var functions = _.assign({
    date: function(file, fileName, sectionName) {
      return file.date || null;
    },
    content: function(file, fileName, sectionName) {
      return MdHelper.render(file.__content);
    },
    preview: function(file, fileName, sectionName) {
      if (file.preview) {
        return file.preview;
      }
      else {
        var previewLimit = 100;

        if(!file.content) {
          return;
        }

        var stripped = removeMd(file.__content);

        if (stripped.length > previewLimit) {
          return stripped.substr(0, previewLimit) + '…';
        }

        return stripped;
      }
      return file.preview || MdHelper.getContentPreview(file.__content);
    },
    title: function(file, fileName, sectionName) {
      return file.title;
    },
    url: function(file, fileName, sectionName) {
      return sectionName + '/' + fileName.split('.')[0];
    },
    layout: function(file, fileName, sectionName) {
      return layout;
    },
  }, themeFunctions, siteFunctions, sectionFunctions);

  _.forEach(functions, function(fn, name) {
    o[name] = fn(o, fileName, sectionName);
  });

  o.section = sectionName;

  return o;
}
<|endoftext|>


<commit_before>// Generated on 2017-02-04 using generator-angular 0.15.1
'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) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn',
    buildcontrol: 'grunt-build-control'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    buildcontrol: {
      options: {
        dir: 'dist',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'},
        pages: {
          options: {
            remote: 'https://github.com/lariosw/programmingsite.git',
            branch: 'gh-pages'
          }
        }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      sass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['sass:server']

      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9013,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35719
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

// Compiles Sass to CSS and generates necessary files if requested
    sass: {
      options: {
        includePaths: [
          'bower_components'
        ] },
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/styles',
          src: ['*.scss'],
          dest: '.tmp/styles',
          ext: '.css'
        }] },
      server: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/styles',
          src: ['*.scss'],
          dest: '.tmp/styles',
          ext: '.css'
        }] }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              //css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
     cssmin: {
     dist: {
       files: {
       '<%= yeoman.dist %>/styles/main.css': [
       '.tmp/styles/{,*/}*.css'
        ]
       }
      }
     },
     uglify: {
       dist: {
         files: {
           '<%= yeoman.dist %>/scripts/scripts.js': [
             '<%= yeoman.dist %>/scripts/scripts.js'
           ]
         }
       }
     },
     concat: {
       dist: {}
     },

    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: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'programmingsiteApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // 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}',
            '*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
// Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'sass:server',
        'copy:styles'
      ], test: [
        'copy:styles'
      ], dist: [
        'sass',
        'copy:styles',
        'imagemin',
        'svgmin'
      ] },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<commit_msg>- fixing grunt tasks so that vendor.css is generated<commit_after>// Generated on 2017-02-04 using generator-angular 0.15.1
'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) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn',
    buildcontrol: 'grunt-build-control'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    buildcontrol: {
      options: {
        dir: 'dist',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'},
        pages: {
          options: {
            remote: 'https://github.com/lariosw/programmingsite.git',
            branch: 'gh-pages'
          }
        }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      sass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['sass:server']

      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35720
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

// Compiles Sass to CSS and generates necessary files if requested
    sass: {
      options: {
        includePaths: [
          'bower_components'
        ] },
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/styles',
          src: ['*.scss'],
          dest: '.tmp/styles',
          ext: '.css'
        }] },
      server: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/styles',
          src: ['*.scss'],
          dest: '.tmp/styles',
          ext: '.css'
        }] }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    //  cssmin: {
    //  dist: {
    //    files: {
    //    '<%= yeoman.dist %>/styles/main.css': [
    //    '.tmp/styles/{,*/}*.css'
    //     ]
    //    }
    //   }
    //  },
    //  uglify: {
    //    dist: {
    //      files: {
    //        '<%= yeoman.dist %>/scripts/scripts.js': [
    //          '<%= yeoman.dist %>/scripts/scripts.js'
    //        ]
    //      }
    //    }
    //  },
    //  concat: {
    //    dist: {}
    //  },

    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: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'programmingsiteApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // 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}',
            '*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
// Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'sass:server',
        'copy:styles'
      ], test: [
        'copy:styles'
      ], dist: [
        'sass',
        'copy:styles',
        'imagemin',
        'svgmin'
      ] },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>/* jshint node: true */

module.exports = function(grunt) {
  "use strict";

  // Project configuration.
  grunt.initConfig({

    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    banner: '/**\n' +
              '* <%= pkg.name %>.js v<%= pkg.version %> by @fat and @mdo\n' +
              '* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
              '* <%= _.pluck(pkg.licenses, "url").join(", ") %>\n' +
              '*/\n',
    jqueryCheck: 'if (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n',

    // Task configuration.
    clean: {
      dist: ['dist']
    },

    jshint: {
      options: {
        jshintrc: 'js/.jshintrc'
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      src: {
        src: ['js/*.js']
      },
      test: {
        src: ['js/tests/unit/*.js']
      }
    },

    concat: {
      options: {
        banner: '<%= banner %><%= jqueryCheck %>',
        stripBanners: false
      },
      bootstrap: {
        src: [
          'js/transition.js',
          'js/alert.js',
          'js/button.js',
          'js/carousel.js',
          'js/collapse.js',
          'js/dropdown.js',
          'js/modal.js',
          'js/tooltip.js',
          'js/popover.js',
          'js/scrollspy.js',
          'js/tab.js',
          'js/affix.js'
        ],
        dest: 'dist/js/<%= pkg.name %>.js'
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      bootstrap: {
        src: ['<%= concat.bootstrap.dest %>'],
        dest: 'dist/js/<%= pkg.name %>.min.js'
      }
    },

    recess: {
      options: {
        compile: true
      },
      bootstrap: {
        src: ['less/bootstrap.less'],
        dest: 'dist/css/<%= pkg.name %>.css'
      },
      min: {
        options: {
          compress: true
        },
        src: ['less/bootstrap.less'],
        dest: 'dist/css/<%= pkg.name %>.min.css'
      },
      theme: {
        src: ['less/theme.less'],
        dest: 'dist/css/<%= pkg.name %>-theme.css'
      },
      theme_min: {
        options: {
          compress: true
        },
        src: ['less/theme.less'],
        dest: 'dist/css/<%= pkg.name %>-theme.min.css'
      }
    },

    copy: {
      fonts: {
        expand: true,
        src: ["fonts/*"],
        dest: 'dist/'
      }
    },

    qunit: {
      options: {
        inject: 'js/tests/unit/phantom.js'
      },
      files: ['js/tests/*.html']
    },

    connect: {
      server: {
        options: {
          port: 3000,
          base: '.'
        }
      }
    },

    jekyll: {
      docs: {}
    },

    validation: {
      options: {
        reset: true,
      },
      files: {
        src: ["_gh_pages/**/*.html"]
      }
    },

    watch: {
      src: {
        files: '<%= jshint.src.src %>',
        tasks: ['jshint:src', 'qunit']
      },
      test: {
        files: '<%= jshint.test.src %>',
        tasks: ['jshint:test', 'qunit']
      },
      recess: {
        files: 'less/*.less',
        tasks: ['recess']
      }
    }
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-qunit');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-html-validation');
  grunt.loadNpmTasks('grunt-jekyll');
  grunt.loadNpmTasks('grunt-recess');
  grunt.loadNpmTasks('browserstack-runner');

  // Docs HTML validation task
  grunt.registerTask('validate-docs', ['jekyll', 'validation']);

  // Test task.
  var testSubtasks = ['jshint', 'qunit', 'validate-docs'];
  // Only run BrowserStack tests under Travis
  if (process.env.TRAVIS) {
    // Only run BrowserStack tests if this is a mainline commit in twbs/bootstrap, or you have your own BrowserStack key
    if ((process.env.TRAVIS_REPO_SLUG === 'twbs/bootstrap' && process.env.TRAVIS_PULL_REQUEST === 'false') || process.env.TWBS_HAVE_OWN_BROWSERSTACK_KEY) {
      testSubtasks.push('browserstack_runner');
    }
  }
  grunt.registerTask('test', testSubtasks);

  // JS distribution task.
  grunt.registerTask('dist-js', ['concat', 'uglify']);

  // CSS distribution task.
  grunt.registerTask('dist-css', ['recess']);

  // Fonts distribution task.
  grunt.registerTask('dist-fonts', ['copy']);

  // Full distribution task.
  grunt.registerTask('dist', ['clean', 'dist-css', 'dist-fonts', 'dist-js']);

  // Default task.
  grunt.registerTask('default', ['test', 'dist', 'build-customizer']);

  // task for building customizer
  grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () {
    var fs = require('fs')

    function getFiles(type) {
      var files = {}
      fs.readdirSync(type)
        .filter(function (path) {
          return new RegExp('\\.' + type + '$').test(path)
        })
        .forEach(function (path) {
          return files[path] = fs.readFileSync(type + '/' + path, 'utf8')
        })
      return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'
    }

    var customize = fs.readFileSync('customize.html', 'utf-8')
    var files = '<!-- generated -->\n<script id="files">\n' + getFiles('js') + getFiles('less') + '<\/script>\n<!-- /generated -->'
    fs.writeFileSync('customize.html', customize.replace(/<!-- generated -->(.|[\n\r])*<!-- \/generated -->/, files))
  });
};
<commit_msg>rename HTML5 validation Grunt task since it checks the examples too<commit_after>/* jshint node: true */

module.exports = function(grunt) {
  "use strict";

  // Project configuration.
  grunt.initConfig({

    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    banner: '/**\n' +
              '* <%= pkg.name %>.js v<%= pkg.version %> by @fat and @mdo\n' +
              '* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
              '* <%= _.pluck(pkg.licenses, "url").join(", ") %>\n' +
              '*/\n',
    jqueryCheck: 'if (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n',

    // Task configuration.
    clean: {
      dist: ['dist']
    },

    jshint: {
      options: {
        jshintrc: 'js/.jshintrc'
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      src: {
        src: ['js/*.js']
      },
      test: {
        src: ['js/tests/unit/*.js']
      }
    },

    concat: {
      options: {
        banner: '<%= banner %><%= jqueryCheck %>',
        stripBanners: false
      },
      bootstrap: {
        src: [
          'js/transition.js',
          'js/alert.js',
          'js/button.js',
          'js/carousel.js',
          'js/collapse.js',
          'js/dropdown.js',
          'js/modal.js',
          'js/tooltip.js',
          'js/popover.js',
          'js/scrollspy.js',
          'js/tab.js',
          'js/affix.js'
        ],
        dest: 'dist/js/<%= pkg.name %>.js'
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      bootstrap: {
        src: ['<%= concat.bootstrap.dest %>'],
        dest: 'dist/js/<%= pkg.name %>.min.js'
      }
    },

    recess: {
      options: {
        compile: true
      },
      bootstrap: {
        src: ['less/bootstrap.less'],
        dest: 'dist/css/<%= pkg.name %>.css'
      },
      min: {
        options: {
          compress: true
        },
        src: ['less/bootstrap.less'],
        dest: 'dist/css/<%= pkg.name %>.min.css'
      },
      theme: {
        src: ['less/theme.less'],
        dest: 'dist/css/<%= pkg.name %>-theme.css'
      },
      theme_min: {
        options: {
          compress: true
        },
        src: ['less/theme.less'],
        dest: 'dist/css/<%= pkg.name %>-theme.min.css'
      }
    },

    copy: {
      fonts: {
        expand: true,
        src: ["fonts/*"],
        dest: 'dist/'
      }
    },

    qunit: {
      options: {
        inject: 'js/tests/unit/phantom.js'
      },
      files: ['js/tests/*.html']
    },

    connect: {
      server: {
        options: {
          port: 3000,
          base: '.'
        }
      }
    },

    jekyll: {
      docs: {}
    },

    validation: {
      options: {
        reset: true,
      },
      files: {
        src: ["_gh_pages/**/*.html"]
      }
    },

    watch: {
      src: {
        files: '<%= jshint.src.src %>',
        tasks: ['jshint:src', 'qunit']
      },
      test: {
        files: '<%= jshint.test.src %>',
        tasks: ['jshint:test', 'qunit']
      },
      recess: {
        files: 'less/*.less',
        tasks: ['recess']
      }
    }
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-qunit');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-html-validation');
  grunt.loadNpmTasks('grunt-jekyll');
  grunt.loadNpmTasks('grunt-recess');
  grunt.loadNpmTasks('browserstack-runner');

  // Docs HTML validation task
  grunt.registerTask('validate-html', ['jekyll', 'validation']);

  // Test task.
  var testSubtasks = ['jshint', 'qunit', 'validate-html'];
  // Only run BrowserStack tests under Travis
  if (process.env.TRAVIS) {
    // Only run BrowserStack tests if this is a mainline commit in twbs/bootstrap, or you have your own BrowserStack key
    if ((process.env.TRAVIS_REPO_SLUG === 'twbs/bootstrap' && process.env.TRAVIS_PULL_REQUEST === 'false') || process.env.TWBS_HAVE_OWN_BROWSERSTACK_KEY) {
      testSubtasks.push('browserstack_runner');
    }
  }
  grunt.registerTask('test', testSubtasks);

  // JS distribution task.
  grunt.registerTask('dist-js', ['concat', 'uglify']);

  // CSS distribution task.
  grunt.registerTask('dist-css', ['recess']);

  // Fonts distribution task.
  grunt.registerTask('dist-fonts', ['copy']);

  // Full distribution task.
  grunt.registerTask('dist', ['clean', 'dist-css', 'dist-fonts', 'dist-js']);

  // Default task.
  grunt.registerTask('default', ['test', 'dist', 'build-customizer']);

  // task for building customizer
  grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () {
    var fs = require('fs')

    function getFiles(type) {
      var files = {}
      fs.readdirSync(type)
        .filter(function (path) {
          return new RegExp('\\.' + type + '$').test(path)
        })
        .forEach(function (path) {
          return files[path] = fs.readFileSync(type + '/' + path, 'utf8')
        })
      return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'
    }

    var customize = fs.readFileSync('customize.html', 'utf-8')
    var files = '<!-- generated -->\n<script id="files">\n' + getFiles('js') + getFiles('less') + '<\/script>\n<!-- /generated -->'
    fs.writeFileSync('customize.html', customize.replace(/<!-- generated -->(.|[\n\r])*<!-- \/generated -->/, files))
  });
};
<|endoftext|>