<commit_before>// Generated on 2014-03-23 using generator-webapp 0.4.8
'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) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

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

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

        // Project settings
        config: {
            // Configurable paths
            app: 'app',
            dist: 'dist',
            prebake: 'appPreBake'
        },

        bake: {
            build: {
                options: {
                    basePath: 'appPreBake'
                },
                files: {
                    // Files that use templates should live in appPreBake.
                    // Add new files to the list below so that they will be
                    // added to the app/ folder, where they are served for the
                    // test server. When built they are compiled and put in the
                    // dist folder.
                    //
                    // grunt-bake adopts the formula:
                    // outputFile: templateFile
                    '<%= config.app %>/index.html': '<%= config.prebake %>/index.html',
                    '<%= config.app %>/first/index.html': '<%= config.prebake %>/first/index.html',
                    '<%= config.app %>/second/index.html': '<%= config.prebake %>/second/index.html',
                    '<%= config.app %>/third/index.html': '<%= config.prebake %>/third/index.html'
                }
            }
        },

        // Watches files for changes and runs tasks based on the changed files
        watch: {
            // We want to rerun bake every time we change a template file in
            // the prebake directory.
            bake: {
                files: ['appPreBake/**'],
                tasks: 'bake:build'
            },
            bower: {
                files: ['bower.json'],
                tasks: ['bowerInstall']
            },
            js: {
                files: ['<%= config.app %>/scripts/{,*/}*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            jstest: {
                files: ['test/spec/{,*/}*.js'],
                tasks: ['test:watch']
            },
            gruntfile: {
                files: ['Gruntfile.js']
            },
            styles: {
                files: ['<%= config.app %>/styles/{,*/}*.css'],
                tasks: ['newer:copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: '<%= connect.options.livereload %>'
                },
                files: [
                    '<%= config.app %>/{,*/}*.html',
                    '.tmp/styles/{,*/}*.css',
                    '<%= config.app %>/images/{,*/}*'
                ]
            }
        },

        // The actual grunt server settings
        connect: {
            options: {
                port: 9000,
                livereload: 35729,
                // Change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    open: true,
                    base: [
                        '.tmp',
                        '<%= config.app %>'
                    ]
                }
            },
            test: {
                options: {
                    port: 9001,
                    base: [
                        '.tmp',
                        'test',
                        '<%= config.app %>'
                    ]
                }
            },
            dist: {
                options: {
                    open: true,
                    base: '<%= config.dist %>',
                    livereload: false
                }
            }
        },

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

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
            options: {
                jshintrc: '.jshintrc',
                reporter: require('jshint-stylish')
            },
            all: [
                'Gruntfile.js',
                '<%= config.app %>/scripts/{,*/}*.js',
                '!<%= config.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },

        // Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

        // Add vendor prefixed styles
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

        // Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                ignorePath: '<%= config.app %>/'
            }
        },

        // Renames files for browser caching purposes
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

        // 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: {
            options: {
                dest: '<%= config.dist %>'
            },
            html: '<%= config.app %>/index.html'
        },

        // Performs rewrites based on rev and the useminPrepare configuration
        usemin: {
            options: {
                assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
            },
            html: ['<%= config.dist %>/{,*/}*.html'],
            css: ['<%= config.dist %>/styles/{,*/}*.css']
        },

        // The following *-min tasks produce minified files in the dist folder
        imagemin: {
            // There are several issues with this task in version 0.5.x. If you
            // are encountering problems where it hangs, claims to not find
            // files, or progresses on subsequent runs but emitting images of
            // size 0, uncomment this options object. It will stop caching and
            // this should fix the problem, although it will take longer.
            // For a more thorough discussion, see the following links:
            // https://github.com/gruntjs/grunt-contrib-imagemin/issues/140
            // http://stackoverflow.com/questions/21175673/grunt-contrib-imagemin-output-fatal-error-enoent-no-such-file-or-directory
            //options: {
            //    cache: false
            //},
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.{gif,jpeg,jpg,png}',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        svgmin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.svg',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        htmlmin: {
            dist: {
                options: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true,
                    removeCommentsFromCDATA: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true
                },
                files: [{
                    expand: true,
                    cwd: '<%= config.dist %>',
                    src: '{,*/}*.html',
                    dest: '<%= config.dist %>'
                }]
            }
        },

        // 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: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

        // Copies remaining files to places other tasks can use
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*',
                        'bower_components/bootstrap/dist/fonts/*.*'
                    ]
                }, {
                    // Have to manually add this copying to ensure that the
                    // glyphicons make it over.
                    // This solution comes from this stack overflow:
                    // http://stackoverflow.com/questions/18572941/why-does-yeoman-build-without-glyphicons
                    expand: true,
                    cwd: '<%= config.app %>/bower_components/bootstrap/dist/fonts',
                    dest: '<%= config.dist %>/fonts',
                    src: '*.*'
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

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

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

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

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

    grunt.registerTask('test', function (target) {
        if (target !== 'watch') {
            grunt.task.run([
                'clean:server',
                'concurrent:test',
                'autoprefixer'
            ]);
        }

        grunt.task.run([
            'connect:test',
            'mocha'
        ]);
    });

    grunt.registerTask('build', [
        'clean:dist',
        'bake',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'cssmin',
        'uglify',
        'copy:dist',
        'rev',
        'usemin',
        'htmlmin'
    ]);

    grunt.registerTask('default', [
        'newer:jshint',
        'test',
        'build'
    ]);
};
<commit_msg>improved comment about source of the glyphicons fix<commit_after>// Generated on 2014-03-23 using generator-webapp 0.4.8
'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) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

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

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

        // Project settings
        config: {
            // Configurable paths
            app: 'app',
            dist: 'dist',
            prebake: 'appPreBake'
        },

        bake: {
            build: {
                options: {
                    basePath: 'appPreBake'
                },
                files: {
                    // Files that use templates should live in appPreBake.
                    // Add new files to the list below so that they will be
                    // added to the app/ folder, where they are served for the
                    // test server. When built they are compiled and put in the
                    // dist folder.
                    //
                    // grunt-bake adopts the formula:
                    // outputFile: templateFile
                    '<%= config.app %>/index.html': '<%= config.prebake %>/index.html',
                    '<%= config.app %>/first/index.html': '<%= config.prebake %>/first/index.html',
                    '<%= config.app %>/second/index.html': '<%= config.prebake %>/second/index.html',
                    '<%= config.app %>/third/index.html': '<%= config.prebake %>/third/index.html'
                }
            }
        },

        // Watches files for changes and runs tasks based on the changed files
        watch: {
            // We want to rerun bake every time we change a template file in
            // the prebake directory.
            bake: {
                files: ['appPreBake/**'],
                tasks: 'bake:build'
            },
            bower: {
                files: ['bower.json'],
                tasks: ['bowerInstall']
            },
            js: {
                files: ['<%= config.app %>/scripts/{,*/}*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            jstest: {
                files: ['test/spec/{,*/}*.js'],
                tasks: ['test:watch']
            },
            gruntfile: {
                files: ['Gruntfile.js']
            },
            styles: {
                files: ['<%= config.app %>/styles/{,*/}*.css'],
                tasks: ['newer:copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: '<%= connect.options.livereload %>'
                },
                files: [
                    '<%= config.app %>/{,*/}*.html',
                    '.tmp/styles/{,*/}*.css',
                    '<%= config.app %>/images/{,*/}*'
                ]
            }
        },

        // The actual grunt server settings
        connect: {
            options: {
                port: 9000,
                livereload: 35729,
                // Change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    open: true,
                    base: [
                        '.tmp',
                        '<%= config.app %>'
                    ]
                }
            },
            test: {
                options: {
                    port: 9001,
                    base: [
                        '.tmp',
                        'test',
                        '<%= config.app %>'
                    ]
                }
            },
            dist: {
                options: {
                    open: true,
                    base: '<%= config.dist %>',
                    livereload: false
                }
            }
        },

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

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
            options: {
                jshintrc: '.jshintrc',
                reporter: require('jshint-stylish')
            },
            all: [
                'Gruntfile.js',
                '<%= config.app %>/scripts/{,*/}*.js',
                '!<%= config.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },

        // Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

        // Add vendor prefixed styles
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

        // Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                ignorePath: '<%= config.app %>/'
            }
        },

        // Renames files for browser caching purposes
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

        // 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: {
            options: {
                dest: '<%= config.dist %>'
            },
            html: '<%= config.app %>/index.html'
        },

        // Performs rewrites based on rev and the useminPrepare configuration
        usemin: {
            options: {
                assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
            },
            html: ['<%= config.dist %>/{,*/}*.html'],
            css: ['<%= config.dist %>/styles/{,*/}*.css']
        },

        // The following *-min tasks produce minified files in the dist folder
        imagemin: {
            // There are several issues with this task in version 0.5.x. If you
            // are encountering problems where it hangs, claims to not find
            // files, or progresses on subsequent runs but emitting images of
            // size 0, uncomment this options object. It will stop caching and
            // this should fix the problem, although it will take longer.
            // For a more thorough discussion, see the following links:
            // https://github.com/gruntjs/grunt-contrib-imagemin/issues/140
            // http://stackoverflow.com/questions/21175673/grunt-contrib-imagemin-output-fatal-error-enoent-no-such-file-or-directory
            //options: {
            //    cache: false
            //},
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.{gif,jpeg,jpg,png}',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        svgmin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.svg',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        htmlmin: {
            dist: {
                options: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true,
                    removeCommentsFromCDATA: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true
                },
                files: [{
                    expand: true,
                    cwd: '<%= config.dist %>',
                    src: '{,*/}*.html',
                    dest: '<%= config.dist %>'
                }]
            }
        },

        // 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: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

        // Copies remaining files to places other tasks can use
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*',
                        'bower_components/bootstrap/dist/fonts/*.*'
                    ]
                }, {
                    // Have to manually add this copying to ensure that the
                    // glyphicons make it over.
                    // This solution comes from:
                    // http://stackoverflow.com/questions/18572941/why-does-yeoman-build-without-glyphicons
                    expand: true,
                    cwd: '<%= config.app %>/bower_components/bootstrap/dist/fonts',
                    dest: '<%= config.dist %>/fonts',
                    src: '*.*'
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

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

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

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

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

    grunt.registerTask('test', function (target) {
        if (target !== 'watch') {
            grunt.task.run([
                'clean:server',
                'concurrent:test',
                'autoprefixer'
            ]);
        }

        grunt.task.run([
            'connect:test',
            'mocha'
        ]);
    });

    grunt.registerTask('build', [
        'clean:dist',
        'bake',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'cssmin',
        'uglify',
        'copy:dist',
        'rev',
        'usemin',
        'htmlmin'
    ]);

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


<commit_before>var shell = require('shelljs');
var inquirer = require('inquirer');

module.exports = function(grunt) {
  grunt.registerTask('publish', 'Publish package to npm.', function() {
    var done = this.async();

    grunt.log.write('Creating package...');

    var result = shell.exec('npm pack', { silent: true });
    if (result.code == 0) {
      grunt.log.ok();
      grunt.log.write();
    } else {
      grunt.log.error();
      grunt.log.error('Error creating package:\n' + result.output);
      done();
      return;
    }

    var archive = result.output.trim();
    shell.exec('tar -ztvf "' + archive + '"');

    var question = {
      type: 'confirm',
      name: 'publish',
      message: 'Publish package?',
      default: false
    };

    inquirer.prompt([question], function(answers) {
      try {
        if (answers.publish) {
          grunt.log.write('Publishing package...');
          var result = shell.exec('npm publish "' + archive + '"', { silent: true });
          if (result.code == 0) {
            grunt.log.ok();
          } else {
            grunt.log.error();
            grunt.log.error('Error publishing package:\n' + result.output);
          }
        }
      } finally {
        grunt.log.write('Removing temporary package...');
        shell.rm(archive);
        grunt.log.ok();
      }

      done();
    });
  });
};
<commit_msg>Simplifying Grunt error logging.<commit_after>var shell = require('shelljs');
var inquirer = require('inquirer');

module.exports = function(grunt) {
  grunt.registerTask('publish', 'Publish package to npm.', function() {
    var done = this.async();

    grunt.log.write('Creating package...');

    var result = shell.exec('npm pack', { silent: true });
    if (result.code == 0) {
      grunt.log.ok().write();
    } else {
      grunt.log.error().error('Error creating package:\n' + result.output);
      done();
      return;
    }

    var archive = result.output.trim();
    shell.exec('tar -ztvf "' + archive + '"');

    var question = {
      type: 'confirm',
      name: 'publish',
      message: 'Publish package?',
      default: false
    };

    inquirer.prompt([question], function(answers) {
      try {
        if (answers.publish) {
          grunt.log.write('Publishing package...');
          var result = shell.exec('npm publish "' + archive + '"', { silent: true });
          if (result.code == 0) {
            grunt.log.ok();
          } else {
            grunt.log.error().error('Error publishing package:\n' + result.output);
          }
        }
      } finally {
        grunt.log.write('Removing temporary package...');
        shell.rm(archive);
        grunt.log.ok();
      }

      done();
    });
  });
};
<|endoftext|>


<commit_before>'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// '<%= config.src %>/templates/pages/{,*/}*.hbs'
// use this if you want to match all subfolders:
// '<%= config.src %>/templates/pages/**/*.hbs'

module.exports = function(grunt) {

  require('time-grunt')(grunt);

  //jit-grunt loads only the npm tasks required for the grunt task.
  //makes livereload much faster.
  require('load-grunt-config')(grunt, {
      jitGrunt: {
          staticMappings: {
              replace: 'grunt-text-replace',
              handlebars: 'grunt-contrib-handlebars',
              resemble: 'grunt-resemble-cli',
              sass: 'grunt-sass',
              connect: 'grunt-contrib-connect',
              jasmine_node: 'grunt-jasmine-node'
          }
      },
      init: true
  });

  grunt.registerTask('staging-deploy', [
    'gitinfo',
    'config:staging',
    'jshint:clientDev',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    'autoprefixer',
    'copy',
    'uglify',
    's3:staging',
    // 'clean:postBuild'
  ]);

  grunt.registerTask('smartling-staging-deploy', [
    'gitinfo',
    'config:smartlingStaging',
    'jshint:clientDev',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    // 'autoprefixer',
    'copy',
    'uglify',
    's3:smartling',
    // 'clean:postBuild'
  ]);

  grunt.registerTask('server', [
    'config:dev',
    'jshint:clientDev',
    'jshint:server',
    'jshint:test',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:dev',
    'replace',
    // 'autoprefixer',
    'copy',
    // 'clean:postBuild',
    'connect:livereload',
    'watch'
  ]);

  grunt.registerTask('build', [
    'config:production',
    'jshint:clientProd',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    // 'autoprefixer',
    'copy',
    'uglify',
    'filerev',
    'userevvd',
    // // 'clean:postBuild'
  ]);

  grunt.registerTask('ui-test', function(which) {
    var task = 'jasmine_node';
    if (which) task += ':' + which;

    grunt.task.run([
      'config:dev',
      'jshint:test',
      task
    ]);
  });

  grunt.registerTask('test', [
    'config:dev',
    'jshint:clientProd',
    'jshint:server',
    'jshint:test',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:dev',
    'replace',
    // 'autoprefixer',
    'copy',
    // 'clean:postBuild',
    'connect:resemble',
    'jasmine_node',
    'resemble'
  ]);

  grunt.registerTask('default', [
    'build'
  ]);

};
<commit_msg>re-enable auto-prefixer<commit_after>'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// '<%= config.src %>/templates/pages/{,*/}*.hbs'
// use this if you want to match all subfolders:
// '<%= config.src %>/templates/pages/**/*.hbs'

module.exports = function(grunt) {

  require('time-grunt')(grunt);

  //jit-grunt loads only the npm tasks required for the grunt task.
  //makes livereload much faster.
  require('load-grunt-config')(grunt, {
      jitGrunt: {
          staticMappings: {
              replace: 'grunt-text-replace',
              handlebars: 'grunt-contrib-handlebars',
              resemble: 'grunt-resemble-cli',
              sass: 'grunt-sass',
              connect: 'grunt-contrib-connect',
              jasmine_node: 'grunt-jasmine-node'
          }
      },
      init: true
  });

  grunt.registerTask('staging-deploy', [
    'gitinfo',
    'config:staging',
    'jshint:clientDev',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    'autoprefixer',
    'copy',
    'uglify',
    's3:staging',
    // 'clean:postBuild'
  ]);

  grunt.registerTask('smartling-staging-deploy', [
    'gitinfo',
    'config:smartlingStaging',
    'jshint:clientDev',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    'autoprefixer',
    'copy',
    'uglify',
    's3:smartling',
    // 'clean:postBuild'
  ]);

  grunt.registerTask('server', [
    'config:dev',
    'jshint:clientDev',
    'jshint:server',
    'jshint:test',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:dev',
    'replace',
    'autoprefixer',
    'copy',
    // 'clean:postBuild',
    'connect:livereload',
    'watch'
  ]);

  grunt.registerTask('build', [
    'config:production',
    'jshint:clientProd',
    'jshint:server',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:prod',
    'autoprefixer',
    'copy',
    'uglify',
    'filerev',
    'userevvd',
    // // 'clean:postBuild'
  ]);

  grunt.registerTask('ui-test', function(which) {
    var task = 'jasmine_node';
    if (which) task += ':' + which;

    grunt.task.run([
      'config:dev',
      'jshint:test',
      task
    ]);
  });

  grunt.registerTask('test', [
    'config:dev',
    'jshint:clientProd',
    'jshint:server',
    'jshint:test',
    'clean:preBuild',
    'assemble',
    'handlebars',
    'modernizr',
    'concat',
    'sass:dev',
    'replace',
    'autoprefixer',
    'copy',
    // 'clean:postBuild',
    'connect:resemble',
    'jasmine_node',
    'resemble'
  ]);

  grunt.registerTask('default', [
    'build'
  ]);

};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      auto: {}
    },
    browserify: {
      client: {
        files: {
          'vendor/html2hscript.js': ['node_modules/html2hscript/index.js']
        }
      }
    },
    concat: {
      options: {
        separator: "\n\n"
      },
      dist: {
        src: [
          'src/_intro.js',
          'src/main.js',
          'src/_outro.js'
        ],
        dest: 'dist/<%= pkg.name.replace(".js", "") %>.js'
      }
    },

    replace: {
      dist: {
        options: {
          patterns: [
            {
              match: 'version',
              replacement: '<%= pkg.version %>'
            }
          ]
        },
        files: [
          {
            expand: true,
            flatten: true,
            src: ['dist/luffa.js', 'dist/luffa.min.js'],
            dest: 'dist/'
          }
        ]
      }
    },
    watch: {
      files: ['src/*.js'],
      tasks: ['concat']
    }
  });

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

  //browserify
  var shell = require('shelljs');
  shell.exec('browserify -r html2hscript -o vendor/html2hscript.js');
  shell.exec('browserify -r is-object -o vendor/is-object.js');

  grunt.registerTask('default', ['concat', 'replace', 'karma']);
};
<commit_msg>update tasks<commit_after>module.exports = function (grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      auto: {}
    },
    browserify: {
      client: {
        files: {
          'vendor/html2hscript.js': ['node_modules/html2hscript/index.js']
        }
      }
    },
    concat: {
      options: {
        separator: "\n\n"
      },
      dist: {
        src: [
          'src/_intro.js',
          'src/main.js',
          'src/_outro.js'
        ],
        dest: 'dist/<%= pkg.name.replace(".js", "") %>.js'
      }
    },

    replace: {
      dist: {
        options: {
          patterns: [
            {
              match: 'version',
              replacement: '<%= pkg.version %>'
            }
          ]
        },
        files: [
          {
            expand: true,
            flatten: true,
            src: ['dist/luffa.js', 'dist/luffa.min.js'],
            dest: 'dist/'
          }
        ]
      }
    },
    watch: {
      files: ['src/*.js'],
      tasks: ['concat']
    }
  });

  grunt.task.registerTask('vendor', 'A sample task that logs stuff.', function() {
    //browserify
    var shell = require('shelljs');
    shell.mkdir('vendor');
    shell.exec('browserify -r html2hscript -o vendor/html2hscript.js');

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

  grunt.registerTask('default', ['vendor', 'concat', 'replace', 'karma']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-blanket');
  grunt.loadNpmTasks('grunt-coveralls');

  // Add our custom tasks.
  grunt.loadTasks('tasks');

  // Project configuration.
  grunt.initConfig({
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        strict: false,
        globals: {
          describe: false,
          it: false,
          suite: false,
          test: false,
          before: false,
          after: false
        }
      },
      all: {
        src: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js']
      }
    },
    clean: {
      coverage: {
        src: ['lib-cov/']
      }
    },
    copy: {
      test: {
        src: ['test/**'],
        dest: 'lib-cov/'
      }
    },
    blanket: {
      tasks: {
        src: ['tasks/'],
        dest: 'lib-cov/tasks/'
      }
    },
    mochaTest: {
      'spec': {
        options: {
          reporter: 'spec',
          // tests are quite slow as thy spawn node processes
          timeout: 10000
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'html-cov': {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'coverage.html'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'mocha-lcov-reporter': {
        options: {
          reporter: 'mocha-lcov-reporter',
          quiet: true,
          captureFile: 'lcov.info'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'travis-cov': {
        options: {
          reporter: 'travis-cov'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      }
    },
    coveralls: {
      all: {
        src: 'lcov.info'
      }
    }
  });

  // Default task.
  grunt.registerTask('build', ['clean', 'blanket', 'copy']);
  grunt.registerTask('default', ['jshint', 'build', 'mochaTest']);
  grunt.registerTask('ci', ['default', 'coveralls']);
};
<commit_msg>Failure to send report to coveralls should not be fatal<commit_after>module.exports = function(grunt) {

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-blanket');
  grunt.loadNpmTasks('grunt-coveralls');

  // Add our custom tasks.
  grunt.loadTasks('tasks');

  // Project configuration.
  grunt.initConfig({
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        strict: false,
        globals: {
          describe: false,
          it: false,
          suite: false,
          test: false,
          before: false,
          after: false
        }
      },
      all: {
        src: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js']
      }
    },
    clean: {
      coverage: {
        src: ['lib-cov/']
      }
    },
    copy: {
      test: {
        src: ['test/**'],
        dest: 'lib-cov/'
      }
    },
    blanket: {
      tasks: {
        src: ['tasks/'],
        dest: 'lib-cov/tasks/'
      }
    },
    mochaTest: {
      'spec': {
        options: {
          reporter: 'spec',
          // tests are quite slow as thy spawn node processes
          timeout: 10000
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'html-cov': {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'coverage.html'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'mocha-lcov-reporter': {
        options: {
          reporter: 'mocha-lcov-reporter',
          quiet: true,
          captureFile: 'lcov.info'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      },
      'travis-cov': {
        options: {
          reporter: 'travis-cov'
        },
        src: ['lib-cov/test/tasks/**/*.js']
      }
    },
    coveralls: {
      options: {
        force: true
      },
      all: {
        src: 'lcov.info'
      }
    }
  });

  // Default task.
  grunt.registerTask('build', ['clean', 'blanket', 'copy']);
  grunt.registerTask('default', ['jshint', 'build', 'mochaTest']);
  grunt.registerTask('ci', ['default', 'coveralls']);
};
<|endoftext|>


<commit_before>(function () {
'use strict';

module.exports = function(grunt) {
	// Unified Watch Object
	var watchFiles = {
		serverViews: ['app/views/**/*.*'],
		serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js'],
		clientViews: ['public/modules/**/views/**/*.html'],
		clientJS: ['public/js/*.js', 'public/modules/**/*.js'],
		clientCSS: ['public/modules/**/*.css'],
		mochaTests: ['app/tests/**/*.js']
	};

	// Project Configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		watch: {
			serverViews: {
				files: watchFiles.serverViews,
				options: {
					livereload: true
				}
			},
			serverJS: {
				files: watchFiles.serverJS,
				tasks: ['jshint'],
				options: {
					livereload: true
				}
			},
			clientViews: {
				files: watchFiles.clientViews,
				options: {
					livereload: true,
				}
			},
			clientJS: {
				files: watchFiles.clientJS,
				tasks: ['jshint'],
				options: {
					livereload: true
				}
			},
			clientCSS: {
				files: watchFiles.clientCSS,
				tasks: ['csslint'],
				options: {
					livereload: true
				}
			}
		},
		jshint: {
			all: {
				src: watchFiles.clientJS.concat(watchFiles.serverJS),
				options: {
					jshintrc: true
				}
			}
		},
		csslint: {
			options: {
				csslintrc: '.csslintrc',
			},
			all: {
				src: watchFiles.clientCSS
			}
		},
		uglify: {
			production: {
				options: {
					mangle: false
				},
				files: {
					'public/dist/application.min.js': 'public/dist/application.js'
				}
			}
		},
		cssmin: {
			combine: {
				files: {
					'public/dist/application.min.css': '<%= applicationCSSFiles %>'
				}
			}
		},
		nodemon: {
			dev: {
				script: 'server.js',
				options: {
					nodeArgs: ['--debug'],
					ext: 'js,html',
					watch: watchFiles.serverViews.concat(watchFiles.serverJS)
				}
			}
		},
		'node-inspector': {
			custom: {
				options: {
					'web-port': 1337,
					'web-host': 'localhost',
					'debug-port': 5858,
					'save-live-edit': true,
					'no-preload': true,
					'stack-trace-limit': 50,
					'hidden': []
				}
			}
		},
		ngAnnotate: {
			production: {
				files: {
					'public/dist/application.js': '<%= applicationJavaScriptFiles %>'
				}
			}
		},
		concurrent: {
			default: ['nodemon', 'watch'],
			debug: ['nodemon', 'watch', 'node-inspector'],
			options: {
				logConcurrentOutput: true,
				limit: 10
			}
		},
		env: {
			test: {
				NODE_ENV: 'test'
			},
			secure: {
				NODE_ENV: 'secure'
			}
		},
		mochaTest: {
			src: watchFiles.mochaTests,
			options: {
				reporter: 'spec',
				require: 'server.js'
			}
		},
		karma: {
			unit: {
				configFile: 'karma.conf.js'
			}
		}
	});

	// Load NPM tasks
	require('load-grunt-tasks')(grunt);

	// Making grunt default to force in order not to break the project.
	grunt.option('force', true);
	grunt.option('verbose', true);

	// A Task for loading the configuration object
	grunt.task.registerTask('loadConfig', 'Task that loads the config into a grunt option.', function() {
		var init = require('./config/init')();

		// It ignores files either for dev or prod
		// var config = require('./config/config');

		// It loads every file included by the project regardless NODE_ENV
		// It makes sence because it's packing min file.
		var all_config = require('./config/env/all');

		grunt.config.set('applicationJavaScriptFiles', all_config.assets.js);
		grunt.config.set('applicationCSSFiles', all_config.assets.css);
	});

	// Default task(s).
	grunt.registerTask('default', ['lint', 'concurrent:default']);

	// Debug task.
	grunt.registerTask('debug', ['lint', 'concurrent:debug']);

	// Secure task(s).
	grunt.registerTask('secure', ['env:secure', 'lint', 'concurrent:default']);

	// Lint task(s).
	grunt.registerTask('lint', ['jshint', 'csslint']);

	// Build task(s).
	grunt.registerTask('build', ['lint', 'loadConfig', 'ngAnnotate', 'uglify', 'cssmin']);

	// Test task.
	grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);

	// heroku deployment
	//
	// staging
	grunt.registertask( 'heroku:development', [ 'build' ] );

	// production
	grunt.registerTask( 'heroku:production', [ 'build' ] );
};
}());
<commit_msg>Gruntfile.js fixed<commit_after>(function () {
'use strict';

module.exports = function(grunt) {
	// Unified Watch Object
	var watchFiles = {
		serverViews: ['app/views/**/*.*'],
		serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js'],
		clientViews: ['public/modules/**/views/**/*.html'],
		clientJS: ['public/js/*.js', 'public/modules/**/*.js'],
		clientCSS: ['public/modules/**/*.css'],
		mochaTests: ['app/tests/**/*.js']
	};

	// Project Configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		watch: {
			serverViews: {
				files: watchFiles.serverViews,
				options: {
					livereload: true
				}
			},
			serverJS: {
				files: watchFiles.serverJS,
				tasks: ['jshint'],
				options: {
					livereload: true
				}
			},
			clientViews: {
				files: watchFiles.clientViews,
				options: {
					livereload: true,
				}
			},
			clientJS: {
				files: watchFiles.clientJS,
				tasks: ['jshint'],
				options: {
					livereload: true
				}
			},
			clientCSS: {
				files: watchFiles.clientCSS,
				tasks: ['csslint'],
				options: {
					livereload: true
				}
			}
		},
		jshint: {
			all: {
				src: watchFiles.clientJS.concat(watchFiles.serverJS),
				options: {
					jshintrc: true
				}
			}
		},
		csslint: {
			options: {
				csslintrc: '.csslintrc',
			},
			all: {
				src: watchFiles.clientCSS
			}
		},
		uglify: {
			production: {
				options: {
					mangle: false
				},
				files: {
					'public/dist/application.min.js': 'public/dist/application.js'
				}
			}
		},
		cssmin: {
			combine: {
				files: {
					'public/dist/application.min.css': '<%= applicationCSSFiles %>'
				}
			}
		},
		nodemon: {
			dev: {
				script: 'server.js',
				options: {
					nodeArgs: ['--debug'],
					ext: 'js,html',
					watch: watchFiles.serverViews.concat(watchFiles.serverJS)
				}
			}
		},
		'node-inspector': {
			custom: {
				options: {
					'web-port': 1337,
					'web-host': 'localhost',
					'debug-port': 5858,
					'save-live-edit': true,
					'no-preload': true,
					'stack-trace-limit': 50,
					'hidden': []
				}
			}
		},
		ngAnnotate: {
			production: {
				files: {
					'public/dist/application.js': '<%= applicationJavaScriptFiles %>'
				}
			}
		},
		concurrent: {
			default: ['nodemon', 'watch'],
			debug: ['nodemon', 'watch', 'node-inspector'],
			options: {
				logConcurrentOutput: true,
				limit: 10
			}
		},
		env: {
			test: {
				NODE_ENV: 'test'
			},
			secure: {
				NODE_ENV: 'secure'
			}
		},
		mochaTest: {
			src: watchFiles.mochaTests,
			options: {
				reporter: 'spec',
				require: 'server.js'
			}
		},
		karma: {
			unit: {
				configFile: 'karma.conf.js'
			}
		}
	});

	// Load NPM tasks
	require('load-grunt-tasks')(grunt);

	// Making grunt default to force in order not to break the project.
	grunt.option('force', true);
	grunt.option('verbose', true);

	// A Task for loading the configuration object
	grunt.task.registerTask('loadConfig', 'Task that loads the config into a grunt option.', function() {
		var init = require('./config/init')();

		// It ignores files either for dev or prod
		// var config = require('./config/config');

		// It loads every file included by the project regardless NODE_ENV
		// It makes sence because it's packing min file.
		var all_config = require('./config/env/all');

		grunt.config.set('applicationJavaScriptFiles', all_config.assets.js);
		grunt.config.set('applicationCSSFiles', all_config.assets.css);
	});

	// Default task(s).
	grunt.registerTask('default', ['lint', 'concurrent:default']);

	// Debug task.
	grunt.registerTask('debug', ['lint', 'concurrent:debug']);

	// Secure task(s).
	grunt.registerTask('secure', ['env:secure', 'lint', 'concurrent:default']);

	// Lint task(s).
	grunt.registerTask('lint', ['jshint', 'csslint']);

	// Build task(s).
	grunt.registerTask('build', ['lint', 'loadConfig', 'ngAnnotate', 'uglify', 'cssmin']);

	// Test task.
	grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);

	// heroku deployment
	//
	// staging
	grunt.registerTask( 'heroku:development', [ 'build' ] );

	// production
	grunt.registerTask( 'heroku:production', [ 'build' ] );
};
}());
<|endoftext|>


<commit_before>/**
 * Controls the input history of terminal application.
 *
 * @param {TerminalInput} INPUT
 * @constructor
 */
var TerminalInputHistory = function (INPUT) {

    /**
     * @type {TerminalInput}
     */
    this.INPUT = INPUT;

    /**
     * @type {string[]}
     * @private
     */
    this._history = [""];

    /**
     * @type {number}
     * @private
     */
    this._currentPosition = 0;

    this.initialize();

};

TerminalInputHistory.prototype.STORAGE_NAME = "terminal-inputHistory";

TerminalInputHistory.prototype.MAX_STACK_SIZE = 200;

TerminalInputHistory.prototype.initialize = function () {

    var _this = this,
        storage = this.INPUT.TERMINAL.storage.get(this.STORAGE_NAME);

    window.addEventListener("keydown", function (event) {
        if (event.keyCode === 38) { // UP
            _this.seek(-1);
            _this.INPUT.set(_this.getCurrent());
            event.preventDefault();
            event.cancelBubble();
        } else if (event.keyCode === 40) { // DOWN
            _this.seek(1);
            _this.INPUT.set(_this.getCurrent());
            event.preventDefault();
            event.cancelBubble();
        }
    });

    window.addEventListener("beforeunload", function () {
        _this.INPUT.TERMINAL.storage.set(_this.STORAGE_NAME, _this.exportJSON());
    });

    if (storage) {
        this.importJSON(storage);
        this._currentPosition = this._history.length - 1;
    }

};

/**
 * Imports history from exported object.
 *
 * @param {string} json
 */
TerminalInputHistory.prototype.importJSON = function (json) {

    var data, i;

    try {
        data = JSON.parse(json);
        for (i in this) {
            if (!this.hasOwnProperty(i)) continue;
            this[i] = data[i] || this[i];
        }
    } catch (e) { console.error(e); }

};

/**
 * Extorts history to object.
 *
 * @returns {string}
 */
TerminalInputHistory.prototype.exportJSON = function () {
    return JSON.stringify({ _history: this._history });
};

/**
 * @param {number} delta - 1 or -1 to list history records.
 */
TerminalInputHistory.prototype.seek = function (delta) {
    this._currentPosition = (delta + this._currentPosition) % this._history.length;
    if (this._currentPosition < 0) this._currentPosition += this._history.length;
};

/**
 * Gets history record by its position in memory.
 *
 * @param {number} position
 * @returns {string}
 */
TerminalInputHistory.prototype.get = function (position) {
    return this._history[position] || "";
};

/**
 * Saves text to current history.
 *
 * @param {string} text
 */
TerminalInputHistory.prototype.save = function (text) {

    if (this._history[this._history.length - 2] === text || text === "") {
        this._currentPosition = this._history.length - 1;
        return;
    }

    this._history[this._history.length - 1] = text;
    this._history.push("");

    if (this._history.length > this.MAX_STACK_SIZE) this._history.splice(0, 1);

    this._currentPosition = this._history.length - 1;

};

/**
 * Returns current history record.
 *
 * @returns {string}
 */
TerminalInputHistory.prototype.getCurrent = function () {

    return this._history[this._currentPosition] || "";

};

/**
 * Returns history record with increment. This method changes current work history field.
 *
 * @param {number} increment
 * @returns {string}
 */
TerminalInputHistory.prototype.load = function (increment) {

    this._currentPosition += increment;
    if (this._currentPosition < 0) this._currentPosition = history.length - 1;
    if (this._currentPosition >= history.length) this._currentPosition = 0;
    return this.getCurrent();

};<commit_msg>small fix<commit_after>/**
 * Controls the input history of terminal application.
 *
 * @param {TerminalInput} INPUT
 * @constructor
 */
var TerminalInputHistory = function (INPUT) {

    /**
     * @type {TerminalInput}
     */
    this.INPUT = INPUT;

    /**
     * @type {string[]}
     * @private
     */
    this._history = [""];

    /**
     * @type {number}
     * @private
     */
    this._currentPosition = 0;

    this.initialize();

};

TerminalInputHistory.prototype.STORAGE_NAME = "terminal-inputHistory";

TerminalInputHistory.prototype.MAX_STACK_SIZE = 200;

TerminalInputHistory.prototype.initialize = function () {

    var _this = this,
        storage = this.INPUT.TERMINAL.storage.get(this.STORAGE_NAME);

    window.addEventListener("keydown", function (event) {
        if (event.keyCode === 38) { // UP
            _this.seek(-1);
            _this.INPUT.set(_this.getCurrent());
            event.preventDefault();
            event.cancelBubble = true;
        } else if (event.keyCode === 40) { // DOWN
            _this.seek(1);
            _this.INPUT.set(_this.getCurrent());
            event.preventDefault();
            event.cancelBubble = true;
        }
    });

    window.addEventListener("beforeunload", function () {
        _this.INPUT.TERMINAL.storage.set(_this.STORAGE_NAME, _this.exportJSON());
    });

    if (storage) {
        this.importJSON(storage);
        this._currentPosition = this._history.length - 1;
    }

};

/**
 * Imports history from exported object.
 *
 * @param {string} json
 */
TerminalInputHistory.prototype.importJSON = function (json) {

    var data, i;

    try {
        data = JSON.parse(json);
        for (i in this) {
            if (!this.hasOwnProperty(i)) continue;
            this[i] = data[i] || this[i];
        }
    } catch (e) { console.error(e); }

};

/**
 * Extorts history to object.
 *
 * @returns {string}
 */
TerminalInputHistory.prototype.exportJSON = function () {
    return JSON.stringify({ _history: this._history });
};

/**
 * @param {number} delta - 1 or -1 to list history records.
 */
TerminalInputHistory.prototype.seek = function (delta) {
    this._currentPosition = (delta + this._currentPosition) % this._history.length;
    if (this._currentPosition < 0) this._currentPosition += this._history.length;
};

/**
 * Gets history record by its position in memory.
 *
 * @param {number} position
 * @returns {string}
 */
TerminalInputHistory.prototype.get = function (position) {
    return this._history[position] || "";
};

/**
 * Saves text to current history.
 *
 * @param {string} text
 */
TerminalInputHistory.prototype.save = function (text) {

    if (this._history[this._history.length - 2] === text || text === "") {
        this._currentPosition = this._history.length - 1;
        return;
    }

    this._history[this._history.length - 1] = text;
    this._history.push("");

    if (this._history.length > this.MAX_STACK_SIZE) this._history.splice(0, 1);

    this._currentPosition = this._history.length - 1;

};

/**
 * Returns current history record.
 *
 * @returns {string}
 */
TerminalInputHistory.prototype.getCurrent = function () {

    return this._history[this._currentPosition] || "";

};

/**
 * Returns history record with increment. This method changes current work history field.
 *
 * @param {number} increment
 * @returns {string}
 */
TerminalInputHistory.prototype.load = function (increment) {

    this._currentPosition += increment;
    if (this._currentPosition < 0) this._currentPosition = history.length - 1;
    if (this._currentPosition >= history.length) this._currentPosition = 0;
    return this.getCurrent();

};<|endoftext|>


<commit_before>'use strict';

var paths = {
    js: ['*.js', 'packages/**/*.js', 'test/**/*.js', '!test/coverage/**', '!bower_components/**',
         '!packages/**/node_modules/**', '!packages/contrib/**', '!packages/**/vendor/**', '!packages/**/tests/**', '!test/**'],
    //coffee: ['**/*.coffee'],
    html: ['packages/**/public/**/views/**', 'packages/**/server/views/**'],
    css: ['!bower_components/**', 'packages/**/public/**/css/*.css', '!packages/contrib/**/public/**/css/*.css',
          '!packages/articles/public/assets/vendor/**', '!packages/system/public/assets/css/*.css']
};

module.exports = function (grunt) {

    if (process.env.NODE_ENV !== 'production') {
        require('time-grunt')(grunt);
    }

    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        assets: grunt.file.readJSON('config/assets.json'),
        clean: ['bower_components/build'],
        watch: {
            js: {
                files: paths.js,
                tasks: ['jshint'],
                options: {
                    livereload: true
                    //interval: 1000
                }
            },
            html: {
                files: paths.html,
                options: {
                    livereload: true,
                    interval: 1000
                }
            },
            css: {
                files: paths.css,
                tasks: ['csslint'],
                options: {
                    livereload: true
                }
            },
            //coffee: {
            //    files: paths.coffee,
            //    tasks: ['coffee:compile']
            //}
        },
        //coffee: {
        //    compile: {
        //        expand: true,
        //        bare: true,
        //        flatten: false,
        //        force: true,
        //        // Need to change this to whatever makes sense
        //        cwd: __dirname + '/packages',
        //        dest: __dirname + '/packages',
        //        src: paths.coffee,
        //        ext: '.js'
        //    }
        //},
        jshint: {
            all: {
                src: paths.js,
                options: {
                    jshintrc: true
                }
            }
        },
        uglify: {
            core: {
                options: {
                    mangle: false
                },
                files: ['<%= assets.core.js %>', '<%= assets.core.fonts %>']
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            src: paths.css
        },
        cssmin: {
            core: {
                files: ['<%= assets.core.css %>', '<%= assets.core.fonts %>']
            }
        },
        nodemon: {
            dev: {
                script: 'server.js',
                options: {
                    args: [],
                    ignore: ['node_modules/**'],
                    ext: 'js,html',
                    nodeArgs: ['--debug'],
                    delayTime: 1,
                    cwd: __dirname
                }
            }
        },
        concurrent: {
            tasks: ['nodemon', 'watch'],
            options: {
                logConcurrentOutput: true
            }
        }, // Testing framework
        mochaTest: {
            options: {
                reporter: 'spec',
                require: [
                    'server.js',
                    //'bower_components/angular-mocks/angular-mocks.js',
                    function () {
                        require('meanio/lib/util').preload(__dirname + '/packages/**/server', 'model');
                    }
                ],
                log: true
            },
            src: ['packages/**/server/tests/**/*.js']
        },
        env: {
            test: {
                NODE_ENV: 'test'
            }
        },
        // Unit tests
        karma: {
            unit: {
                configFile: 'karma.conf.js'
            }
        },
        // e2e test
        // Run individual tests like this: grunt e2e --specs=packages/users/public/tests/e2e/users.js
        protractor: {
            options: {
                configFile: 'protractorConf.js', // Default config file
                keepAlive: true, // If false, the grunt process stops when the test fails.
                noColor: false, // If true, protractor will not use colors in its output.
                args: {
                    // Arguments passed to the command
                },
                debug: false
            },
            all: {}
            //your_target: {   // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
            //    options: {
            //        configFile: "e2e.conf.js", // Target-specific config file
            //        args: {} // Target-specific arguments
            //    }
            //}
        }
    });

    //Load NPM tasks
    require('load-grunt-tasks')(grunt);

    //Default task(s).
    if (process.env.NODE_ENV === 'production') {
        // Run and monitoring is done by pm2, not concurrent
        grunt.registerTask('default', ['clean', 'cssmin', 'uglify']);
    } else {
        grunt.registerTask('default', ['clean', 'jshint', 'csslint', 'concurrent']);
    }

    //Test task.
    grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit', 'protractor']);
    grunt.registerTask('mocha', ['env:test', 'mochaTest']);
    grunt.registerTask('karmatest', ['env:test', 'karma:unit']);
    grunt.registerTask('e2e', ['env:test', 'mochaTest', 'protractor']);

    // For Heroku users only.
    // Docs: https://github.com/linnovate/mean/wiki/Deploying-on-Heroku
    //grunt.registerTask('heroku:production', ['cssmin', 'uglify']);
};
<commit_msg>Trying to include fonts<commit_after>'use strict';

var paths = {
    js: ['*.js', 'packages/**/*.js', 'test/**/*.js', '!test/coverage/**', '!bower_components/**',
         '!packages/**/node_modules/**', '!packages/contrib/**', '!packages/**/vendor/**', '!packages/**/tests/**', '!test/**'],
    //coffee: ['**/*.coffee'],
    html: ['packages/**/public/**/views/**', 'packages/**/server/views/**'],
    css: ['!bower_components/**', 'packages/**/public/**/css/*.css', '!packages/contrib/**/public/**/css/*.css',
          '!packages/articles/public/assets/vendor/**', '!packages/system/public/assets/css/*.css']
};

module.exports = function (grunt) {

    if (process.env.NODE_ENV !== 'production') {
        require('time-grunt')(grunt);
    }

    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        assets: grunt.file.readJSON('config/assets.json'),
        clean: ['bower_components/build'],
        watch: {
            js: {
                files: paths.js,
                tasks: ['jshint'],
                options: {
                    livereload: true
                    //interval: 1000
                }
            },
            html: {
                files: paths.html,
                options: {
                    livereload: true,
                    interval: 1000
                }
            },
            css: {
                files: paths.css,
                tasks: ['csslint'],
                options: {
                    livereload: true
                }
            },
            //coffee: {
            //    files: paths.coffee,
            //    tasks: ['coffee:compile']
            //}
        },
        //coffee: {
        //    compile: {
        //        expand: true,
        //        bare: true,
        //        flatten: false,
        //        force: true,
        //        // Need to change this to whatever makes sense
        //        cwd: __dirname + '/packages',
        //        dest: __dirname + '/packages',
        //        src: paths.coffee,
        //        ext: '.js'
        //    }
        //},
        jshint: {
            all: {
                src: paths.js,
                options: {
                    jshintrc: true
                }
            }
        },
        uglify: {
            core: {
                options: {
                    mangle: false
                },
                files: ['<%= assets.core.js %>', '<%= assets.core.fonts %>']
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            src: paths.css
        },
        cssmin: {
            core: {
                files: '<%= assets.core.css %>'
            }
        },
        nodemon: {
            dev: {
                script: 'server.js',
                options: {
                    args: [],
                    ignore: ['node_modules/**'],
                    ext: 'js,html',
                    nodeArgs: ['--debug'],
                    delayTime: 1,
                    cwd: __dirname
                }
            }
        },
        concurrent: {
            tasks: ['nodemon', 'watch'],
            options: {
                logConcurrentOutput: true
            }
        }, // Testing framework
        mochaTest: {
            options: {
                reporter: 'spec',
                require: [
                    'server.js',
                    //'bower_components/angular-mocks/angular-mocks.js',
                    function () {
                        require('meanio/lib/util').preload(__dirname + '/packages/**/server', 'model');
                    }
                ],
                log: true
            },
            src: ['packages/**/server/tests/**/*.js']
        },
        env: {
            test: {
                NODE_ENV: 'test'
            }
        },
        // Unit tests
        karma: {
            unit: {
                configFile: 'karma.conf.js'
            }
        },
        // e2e test
        // Run individual tests like this: grunt e2e --specs=packages/users/public/tests/e2e/users.js
        protractor: {
            options: {
                configFile: 'protractorConf.js', // Default config file
                keepAlive: true, // If false, the grunt process stops when the test fails.
                noColor: false, // If true, protractor will not use colors in its output.
                args: {
                    // Arguments passed to the command
                },
                debug: false
            },
            all: {}
            //your_target: {   // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
            //    options: {
            //        configFile: "e2e.conf.js", // Target-specific config file
            //        args: {} // Target-specific arguments
            //    }
            //}
        }
    });

    //Load NPM tasks
    require('load-grunt-tasks')(grunt);

    //Default task(s).
    if (process.env.NODE_ENV === 'production') {
        // Run and monitoring is done by pm2, not concurrent
        grunt.registerTask('default', ['clean', 'cssmin', 'uglify']);
    } else {
        grunt.registerTask('default', ['clean', 'jshint', 'csslint', 'concurrent']);
    }

    //Test task.
    grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit', 'protractor']);
    grunt.registerTask('mocha', ['env:test', 'mochaTest']);
    grunt.registerTask('karmatest', ['env:test', 'karma:unit']);
    grunt.registerTask('e2e', ['env:test', 'mochaTest', 'protractor']);

    // For Heroku users only.
    // Docs: https://github.com/linnovate/mean/wiki/Deploying-on-Heroku
    //grunt.registerTask('heroku:production', ['cssmin', 'uglify']);
};
<|endoftext|>


<commit_before>isic.models.StudyModel = girder.Model.extend({
    resourceName: 'study',

    /**
     * Add a user to the study.
     */
    addUser: function (userId) {
        girder.restRequest({
            path: this.resourceName + '/' + this.get('_id') + '/user',
            type: 'POST',
            data: {
                userId: userId
            }
        }).done(_.bind(function (resp) {
            this.trigger('g:addedUser');
        }, this)).error(_.bind(function (err) {
            this.trigger('g:error', err);
        }, this));
    }
});
<commit_msg>Add method to check whether a user is a study administrator<commit_after>isic.models.StudyModel = girder.Model.extend({
    resourceName: 'study',

    /**
     * Add a user to the study.
     */
    addUser: function (userId) {
        girder.restRequest({
            path: this.resourceName + '/' + this.get('_id') + '/user',
            type: 'POST',
            data: {
                userId: userId
            }
        }).done(_.bind(function (resp) {
            this.trigger('g:addedUser');
        }, this)).error(_.bind(function (err) {
            this.trigger('g:error', err);
        }, this));
    },

    /**
     * Check whether user is a a study administrator.
     *
     * Returns a promise that is resolved with a single boolean argument that
     * indicates whether the user is a study administrator.
     *
     */
    isAdministrator: function (user) {
        var deferred = $.Deferred();
        if (user) {
            var groups = new girder.collections.GroupCollection();
            groups.once('g:changed', function () {
                if (!groups.isEmpty()) {
                    var groupId = groups.first().id;
                    var userGroups = user.get('groups');
                    var studyAdmin = _.contains(userGroups, groupId);
                    deferred.resolve(studyAdmin);
                } else {
                    deferred.resolve(false);
                }
            }, this).once('g:error', function () {
                deferred.reject();
            }, this).fetch({
                text: 'Study Administrators',
                exact: true
            });
        } else {
            deferred.resolve(false);
        }
        return deferred.promise();
    }
});
<|endoftext|>


<commit_before>// Generated on 2013-06-26 using generator-webapp 0.2.4
'use strict';

var child_process = require('child_process');
var path = require('path');
var proxy = require('proxy-middleware');

var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

var addHeaders = function(headers) {
    return function(req, res, next) {
        for (var key in headers) {
            if (req.url == "/relay.html" && key == "X-Frame-Options")
                continue;
            res.setHeader(key, headers[key]);
        }
        next();
    };
}

var proxyPath = function(route, port) {
    return proxy({
        route: route,
        protocol: 'http:',
        hostname: '127.0.0.1',
        port: port,
        pathname: '/'
    });
};

var KDC_PROXY_PORT = 5001;

// # 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) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: 'out'
    };

    /*
    var appConfig = {
        realm: 'ATHENA.MIT.EDU',
        server: 'https://roost-api.mit.edu',
        serverPrincipal: 'HTTP/roost-api.mit.edu',
        webathena: 'https://webathena.mit.edu'
    };
    if (grunt.option('realm'))
        appConfig.server = grunt.option('realm');
    if (grunt.option('server'))
        appConfig.server = grunt.option('server');
    if (grunt.option('server-principal'))
        appConfig.serverPrincipal = grunt.option('server-principal');
    if (grunt.option('webathena'))
        appConfig.webathena = grunt.option('webathena');
    */

    // Declare non-HSTS headers here, so they can be emitted both to
    // .htaccess and in the dev server.
    var csp = "default-src 'self'; " +
        "style-src 'self' https://fonts.googleapis.com; " +
        "font-src https://themes.googleusercontent.com; " +
        "object-src 'none'";
    var headers = {
        // Standard header; Chrome 25+
        'Content-Security-Policy': csp,
        // Firefox and IE.
        'X-Content-Security-Policy': csp,
        // Safari 6+ and Chrome < 25
        'X-WebKit-CSP': csp,
        // XSS filters can sometimes be abused to selectively disable
        // script tags. With inline script disabled, it's probably
        // fine, but it's configure them to hard-fail anyway.
        'X-XSS-Protection': '1; mode=block',
        // Disallow iframes to do a bit against click-jacking.
        'X-Frame-Options': 'deny',
        // Disable content sniffing, per Tangled Web. Though it's not
        // a huge deal as we're completely static.
        'X-Content-Options': 'nosniff'
    };

    grunt.initConfig({
//        app: appConfig,
        yeoman: yeomanConfig,
        watch: {
            options: {
                nospawn: true
            },
            livereload: {
                options: {
                    livereload: LIVERELOAD_PORT
                },
                files: [
                    '<%= yeoman.app %>/*.html',
                    '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
                ]
            }
        },
        connect: {
            options: {
                port: 5000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            // livereload and CSP don't play well.
                            // lrSnippet,
                            addHeaders(headers),
                            proxyPath('/kdc', KDC_PROXY_PORT),
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, yeomanConfig.app + '/dev-overlay'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test'),
                            mountFolder(connect, yeomanConfig.app + '/dev-overlay'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            addHeaders(headers),
                            proxyPath('/kdc', KDC_PROXY_PORT),
                            mountFolder(connect, yeomanConfig.dist)
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= yeoman.dist %>/*',
                        '!<%= yeoman.dist %>/.git*'
                    ]
                }]
            },
            server: [
               '.tmp',
               '<%= yeoman.app %>/scripts-src/config.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        // not used since Uglify task does concat,
        // but still available if needed
        /*concat: {
            dist: {}
        },*/
        // not enabled since usemin task does concat and uglify
        // check index.html to edit your build targets
        // enable this task if you prefer defining your build targets here
        uglify: {
            options: { preserveComments: 'some' }
        },
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= yeoman.dist %>/scripts/{,*/}*.js',
                        '<%= yeoman.dist %>/styles/{,*/}*.css',
                        '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}',
                        '<%= yeoman.dist %>/styles/fonts/*'
                    ]
                }
            }
        },
        useminPrepare: {
            options: {
                dest: '<%= yeoman.dist %>'
            },
            html: '<%= yeoman.app %>/*.html'
        },
        usemin: {
            options: {
                dirs: ['<%= yeoman.dist %>']
            },
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
        },
        // Put files not handled in other tasks here
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.{webp,gif}',
                        'images/{,*/}*.{png,jpg,jpeg}',
                        'images/{,*/}*.svg',
                        'styles/{,*/}*.css',
			// Anything to be compiled goes in scripts-src/. This
			// directory is things that are already minified.
                        'scripts/{,*/}*.js',
                        '*.html'
                    ]
                }, {
                    expand: true,
                    cwd: '.tmp/images',
                    dest: '<%= yeoman.dist %>/images',
                    src: [
                        'generated/*'
                    ]
                }]
            }
        }
    });

    /*
    grunt.registerTask('config', function() {
        grunt.file.write(yeomanConfig.app + '/scripts-src/config.js',
                         '"use strict"\n' +
                         'var CONFIG = ' + JSON.stringify(appConfig) + ';');

        var htaccess = grunt.file.read(yeomanConfig.app + '/htaccess-header');
        htaccess += '\n';
        for (var key in headers) {
            htaccess += 'Header add ' + key + ' "' +
                headers[key].replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
            if (key == 'X-WebKit-CSP')
                htaccess += ' env=!broken_safari';
            htaccess += '\n';
        }
        htaccess += grunt.file.read(yeomanConfig.app + '/htaccess-footer');
        grunt.file.write(yeomanConfig.app + '/.htaccess', htaccess);
    });
    */

    grunt.registerTask('kdc-proxy', function() {
        grunt.log.writeln('Spawning KDC proxy')
        var kdc = child_process.spawn(
            path.join(yeomanConfig.app, '../kdc/kdc.py'),
            ['127.0.0.1:' + String(KDC_PROXY_PORT)],
            {env: process.env, stdio: 'inherit'});
        kdc.on('exit', function(code) {
            grunt.log.writeln('KDC proxy exitted with code ' + code);
        });
        process.on('exit', function() {
            grunt.log.writeln('Killing KDC proxy')
            kdc.kill();
        });

        // Sleep for 100ms for the proxy to be ready.
        setTimeout(this.async(), 100);
    });

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'kdc-proxy', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
//            'config',
            'kdc-proxy',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
//        'config',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
//        'config',
        'useminPrepare',
        'concat',
        'uglify',
        'copy:dist',
        'rev',
        'usemin'
    ]);

    grunt.registerTask('default', [
        'test',
        'build'
    ]);
};
<commit_msg>Add build rule to export webathena.js<commit_after>// Generated on 2013-06-26 using generator-webapp 0.2.4
'use strict';

var child_process = require('child_process');
var path = require('path');
var proxy = require('proxy-middleware');

var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

var addHeaders = function(headers) {
    return function(req, res, next) {
        for (var key in headers) {
            if (req.url == "/relay.html" && key == "X-Frame-Options")
                continue;
            res.setHeader(key, headers[key]);
        }
        next();
    };
}

var proxyPath = function(route, port) {
    return proxy({
        route: route,
        protocol: 'http:',
        hostname: '127.0.0.1',
        port: port,
        pathname: '/'
    });
};

var KDC_PROXY_PORT = 5001;

// # 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) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: 'out'
    };

    /*
    var appConfig = {
        realm: 'ATHENA.MIT.EDU',
        server: 'https://roost-api.mit.edu',
        serverPrincipal: 'HTTP/roost-api.mit.edu',
        webathena: 'https://webathena.mit.edu'
    };
    if (grunt.option('realm'))
        appConfig.server = grunt.option('realm');
    if (grunt.option('server'))
        appConfig.server = grunt.option('server');
    if (grunt.option('server-principal'))
        appConfig.serverPrincipal = grunt.option('server-principal');
    if (grunt.option('webathena'))
        appConfig.webathena = grunt.option('webathena');
    */

    // Declare non-HSTS headers here, so they can be emitted both to
    // .htaccess and in the dev server.
    var csp = "default-src 'self'; " +
        "style-src 'self' https://fonts.googleapis.com; " +
        "font-src https://themes.googleusercontent.com; " +
        "object-src 'none'";
    var headers = {
        // Standard header; Chrome 25+
        'Content-Security-Policy': csp,
        // Firefox and IE.
        'X-Content-Security-Policy': csp,
        // Safari 6+ and Chrome < 25
        'X-WebKit-CSP': csp,
        // XSS filters can sometimes be abused to selectively disable
        // script tags. With inline script disabled, it's probably
        // fine, but it's configure them to hard-fail anyway.
        'X-XSS-Protection': '1; mode=block',
        // Disallow iframes to do a bit against click-jacking.
        'X-Frame-Options': 'deny',
        // Disable content sniffing, per Tangled Web. Though it's not
        // a huge deal as we're completely static.
        'X-Content-Options': 'nosniff'
    };

    grunt.initConfig({
//        app: appConfig,
        yeoman: yeomanConfig,
        watch: {
            options: {
                nospawn: true
            },
            livereload: {
                options: {
                    livereload: LIVERELOAD_PORT
                },
                files: [
                    '<%= yeoman.app %>/*.html',
                    '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
                ]
            }
        },
        connect: {
            options: {
                port: 5000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            // livereload and CSP don't play well.
                            // lrSnippet,
                            addHeaders(headers),
                            proxyPath('/kdc', KDC_PROXY_PORT),
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, yeomanConfig.app + '/dev-overlay'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test'),
                            mountFolder(connect, yeomanConfig.app + '/dev-overlay'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            addHeaders(headers),
                            proxyPath('/kdc', KDC_PROXY_PORT),
                            mountFolder(connect, yeomanConfig.dist)
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= yeoman.dist %>/*',
                        '!<%= yeoman.dist %>/.git*'
                    ]
                }]
            },
            server: [
               '.tmp',
               '<%= yeoman.app %>/scripts-src/config.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        // not used since Uglify task does concat,
        // but still available if needed
        /*concat: {
            dist: {}
        },*/
        // not enabled since usemin task does concat and uglify
        // check index.html to edit your build targets
        // enable this task if you prefer defining your build targets here
        uglify: {
            options: { preserveComments: 'some' }
        },
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= yeoman.dist %>/scripts/{,*/}*.js',
                        '<%= yeoman.dist %>/styles/{,*/}*.css',
                        '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}',
                        '<%= yeoman.dist %>/styles/fonts/*'
                    ]
                }
            }
        },
        useminPrepare: {
            options: {
                dest: '<%= yeoman.dist %>'
            },
            html: '<%= yeoman.app %>/*.html'
        },
        usemin: {
            options: {
                dirs: ['<%= yeoman.dist %>']
            },
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
        },
        // Put files not handled in other tasks here
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.{webp,gif}',
                        'images/{,*/}*.{png,jpg,jpeg}',
                        'images/{,*/}*.svg',
                        'styles/{,*/}*.css',
			// Anything to be compiled goes in scripts-src/. This
			// directory is things that are already minified.
                        'scripts/{,*/}*.js',
                        '*.html'
                    ]
                }, {
                    expand: true,
                    cwd: '.tmp/images',
                    dest: '<%= yeoman.dist %>/images',
                    src: [
                        'generated/*'
                    ]
                }]
            }
        }
    });

    /*
    grunt.registerTask('config', function() {
        grunt.file.write(yeomanConfig.app + '/scripts-src/config.js',
                         '"use strict"\n' +
                         'var CONFIG = ' + JSON.stringify(appConfig) + ';');

        var htaccess = grunt.file.read(yeomanConfig.app + '/htaccess-header');
        htaccess += '\n';
        for (var key in headers) {
            htaccess += 'Header add ' + key + ' "' +
                headers[key].replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
            if (key == 'X-WebKit-CSP')
                htaccess += ' env=!broken_safari';
            htaccess += '\n';
        }
        htaccess += grunt.file.read(yeomanConfig.app + '/htaccess-footer');
        grunt.file.write(yeomanConfig.app + '/.htaccess', htaccess);
    });
    */

    grunt.registerTask('kdc-proxy', function() {
        grunt.log.writeln('Spawning KDC proxy')
        var kdc = child_process.spawn(
            path.join(yeomanConfig.app, '../kdc/kdc.py'),
            ['127.0.0.1:' + String(KDC_PROXY_PORT)],
            {env: process.env, stdio: 'inherit'});
        kdc.on('exit', function(code) {
            grunt.log.writeln('KDC proxy exitted with code ' + code);
        });
        process.on('exit', function() {
            grunt.log.writeln('Killing KDC proxy')
            kdc.kill();
        });

        // Sleep for 100ms for the proxy to be ready.
        setTimeout(this.async(), 100);
    });

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'kdc-proxy', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
//            'config',
            'kdc-proxy',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
//        'config',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('export-webathena', function() {
        grunt.file.copy(path.join(yeomanConfig.dist, 'scripts/webathena.js'),
                        'dist/webathena.js');
    });

    grunt.registerTask('build', [
        'clean:dist',
//        'config',
        'useminPrepare',
        'concat',
        'uglify',
        'copy:dist',
        'export-webathena',
        'rev',
        'usemin'
    ]);

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