<commit_before>module.exports = function (grunt) {
    var child_process = require('child_process');
    var path = require('path');
    var async = require('async');

    require('jit-grunt')(grunt, {
        'bower': 'grunt-bower-task',
    });

    var jshintFile = './src/js/.jshintrc';

    // Folder containing the Ink source files, Ink/*
    // (Relative to your "js" folder containing ink-all.js)
    // for source maps.
    // If you're serving the whole Ink tree on your server, the below works.
    var sourceMapPathToInkSource = '../../src/js';

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        ink: {
            folders: {
                bower: './bower_components/',
                js: {
                    srcBase: './src/js/',
                    src: './src/js/Ink/',
                    tests: './src/js/tests/',
                    dist: './dist/js/'
                },
                css: {
                    src: './src/sass/',
                    dist: './dist/css/'
                }
            },
            test: {
                connect_port: process.env['INK_TEST_CONNECT_PORT'] || 8000,
                root: '.',
            }
        },
        // handle 3rd party dependencies
        bower: {
            install: {
                options: {
                    copy: false,
                    targetDir: '<%= ink.folders.bower %>',
                    layout: 'byType',
                    install: true,
                    verbose: false,
                    cleanTargetDir: false
                }
            }
        },
        copy: {
            fontAwesome: {
                files: [
                    {
                        cwd: '<%= ink.folders.bower %>font-awesome/scss/',
                        src: '*.scss',
                        dest: 'src/sass/contrib/font-awesome/',
                        expand: true,
                    }
                ]
            },
            animate: {
                files: [{
                    cwd: '<%= ink.folders.bower %>animate.css',
                    src: ['animate.css'],
                    dest: 'src/sass/contrib/animations/',
                    expand: true,
                    rename: function (dest, src) {
                        return dest + 'animate.css';
                    }
                }]
            },
            modernizr: {
                files: [{
                    cwd: '<%= ink.folders.bower %>modernizr',
                    src: 'modernizr.js',
                    dest: '<%= ink.folders.js.dist %>',
                    expand: true
                }]
            },

            compass: {
                files: [
                    {
                        cwd: '<%= ink.folders.bower %>bower-compass-core/compass/stylesheets/',
                        src: '**/*.scss',
                        dest: 'src/sass/contrib/',
                        expand: true,
                    }
                ]
            },
            facss: {
              src: 'dist/css/contrib/font-awesome/font-awesome.css',
              dest: 'dist/css/font-awesome.css'
            }
        },

        // builds the javascript bundles
        concat: {

            // ink.js
            ink: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>',
                    src: [
                        '1/**/lib.js',
                        'Net/**/lib.js',
                        'Dom/**/lib.js',
                        'Util/**/lib.js',
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink.js';
                    }
                }]
            },

            // ink-all.js
            ink_all: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>',
                    src: [
                        '1/**/lib.js',
                        // Don't include autoload
                        'Net/**/lib.js',
                        'Dom/**/lib.js',
                        'Util/**/lib.js',
                        'UI/**/lib.js'
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink-all.js';
                    }
                }]
            },

            // ink-ui.js
            ink_ui: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>UI/',
                    src: [
                        '**/lib.js'
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink-ui.js';
                    }
                }]
            },

            // ui components as single files
            ui: {
                files: [{
                    expand: true,
                    cwd: '<%= ink.folders.js.src %>UI/',
                    src: ['**/[0-9]/lib.js'],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        // check if this is v1
                        // Here data is in the form of [UIComponent]/[ver]/lib.js
                        var split = src.split(/\//);
                        var modName = split[0].toLowerCase();
                        var version = split[1];

                        if (version === '1') {
                            // and it it is discard the version number
                            return dest + 'ink.' + modName + '.js';
                        } else {
                            // or replace the slash by an underscore and version number and prepend to dest file name
                            return dest + 'ink.' + modName + '-' + version + '.js';
                        }
                    }
                }
                ]
            },

            autoload: {
                files: [{
                    expand: true,
                    cwd: '<%= ink.folders.js.src %>Autoload',
                    src: ['**/lib.js'],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        var version = src.split('/')[0];
                        if (version === '1') {
                            return dest + 'autoload.js';
                        } else {
                            return dest + 'autoload-' + version + '.js';
                        }
                    }
                }]
            }
        },

        clean: {
            js: {
                src: [
                    '<%= ink.folders.js.dist %>/ink*.js',
                    '<%= ink.folders.js.dist %>/ink*.js.map',
                ]
            },
            css: {
                src: [
                  '<%= ink.folders.css.dist %>/*.css',
                  '<%= ink.folders.css.dist %>/*.css.map',
                  '!<%= ink.folders.css.dist %>/quick-start.css'
                ]
            },
            csscontrib: [ '<%= ink.folders.css.dist %>/contrib' ]
        },

        // CONCATENATE JS
        uglify: {
            options: {
                report: 'min',
                sourceMapIncludeSources: true,
                compress: {
                    sequences: true,
                    properties: true,
                    dead_code: false,
                    drop_debugger: false,
                    unsafe: false,
                    conditionals: true,
                    comparisons: true,
                    evaluate: true,
                    booleans: true,
                    loops: true,
                    unused: false,
                    hoist_funs: true,
                    hoist_vars: false,
                    if_return: true,
                    join_vars: true,
                    cascade: true
                }
            },
            ink: {
                src: [
                    '<%= ink.folders.js.src %>1/**/lib.js',
                    '<%= ink.folders.js.src %>Net/**/lib.js',
                    '<%= ink.folders.js.src %>Dom/**/lib.js',
                    '<%= ink.folders.js.src %>Util/**/lib.js',
                ],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink.js.map',
                    sourceMappingURL: 'ink.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink.min.js'
            },
            ink_all: {
                src: [
                    '<%= ink.folders.js.src %>1/**/lib.js',
                    // Do not include autoload
                    '<%= ink.folders.js.src %>Net/**/lib.js',
                    '<%= ink.folders.js.src %>Dom/**/lib.js',
                    '<%= ink.folders.js.src %>UI/**/lib.js',
                    '<%= ink.folders.js.src %>Util/**/lib.js',
                ],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink-all.js.map',
                    sourceMappingURL: 'ink-all.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink-all.min.js'
            },
            ink_ui: {
                src: ['<%= ink.folders.js.src %>UI/**/lib.js'],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink-ui.js.map',
                    sourceMappingURL: 'ink-ui.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink-ui.min.js'
            }
        },

        // Runs JSHint on the Ink.js JavaScript source
        jshint: {
            inkjs: {
                options: {
                    jshintrc: '<%= ink.folders.js.srcBase %>.jshintrc'
                },
                files: {
                    src: '<%= ink.folders.js.src %>**/lib.js'
                }
            },
        },

        compass: {
            css: {
                options: {
                    outputStyle: 'expanded',
                    noLineComments: true,
                    relativeAssets: true,
                    sassDir: 'src/sass',
                    cssDir: "dist/css",
                    fontsDir: 'dist/fonts',
                    imagesDir: 'dist/img'
                }
            },
        },

        cssmin: {
            minify: {
                expand: true,
                cwd: '<%= ink.folders.css.dist %>',
                src: ['*.css', '!quick-start.css', '!*min*'],
                dest: '<%= ink.folders.css.dist %>',
                ext: '.min.css',
                options: {
                    keepSpecialComments: 0,
                    report: 'min',
                    sourceMap: true,
                    sourceMapFilename: '<%= ink.folders.css.dist %>ink-min.css.map',
                    sourceMapRootpath: '../../'
                }
            }
        },

        connect: {
            test: {
                options: {
                    port: '<%= ink.test.connect_port %>',
                    base: '<%= ink.test.root %>',
                    keepalive: false
                }
            },
        },

        // Creates a plato report
        plato: {
            inkjs: {
                options: {
                    jshint: grunt.file.readJSON(jshintFile, {
                        encoding: 'utf-8'
                    })
                },
                files: {
                    '<%= ink.folders.js.srcBase %>report': '<%= ink.folders.js.src %>**/lib.js'
                }
            }
        },

        watch: {
            css: {
                files: [
                    'src/**/*.scss'
                ],
                tasks: ['css'],
                options: {
                    spawn: false,
                    interrupt: true,
                }
            },
            js: {
                files: ['<%= ink.folders.js.src %>/**/*.js'],
                tasks: ['js'],
                options: {
                    spawn: false,
                    interrupt: true,
                }
            },
        },

        compress: {
          main: {
            options: {
              archive: 'ink-<%= pkg.version %>.zip',
              mode: "zip",
              level: 9,
              pretty: true
            },
            files: [
              {expand: true, cwd: "dist/", src: ['**'], dest: '/ink-<%= pkg.version %>'} // includes files in path and its subdirs
            ]
          }
        },

        bump : {
            options: {
                files: [ 'bower.json', 'package.json', '<%= ink.folders.js.src %>/1/lib.js'],
                push: false,
                commit: false,
                tagName: '%VERSION%',
                createTag: false,
                commitFiles: []
            }
        }
    });

    grunt.registerTask('js', ['clean:js', 'concat', 'uglify']);
    grunt.registerTask('css', ['clean:css', 'compass', 'copy:facss', 'clean:csscontrib', 'cssmin']);
    grunt.registerTask('dist', ['css', 'js', 'compress']);
    grunt.registerTask('dependencies', ['bower', 'copy:fontAwesome', 'copy:compass']);
    grunt.registerTask('default', ['dependencies','css','js']);
    grunt.registerTask('_phantomjs', function (module) {
        this.requires('connect:test');

        var options = this.options({
            module: '**'
        });

        var failures = [];

        var testFiles = grunt.file.expand('test/unit/' + options.module + '/index.html');

        var done = this.async();

        async.eachSeries(testFiles, function (testFile, next) {
            var url = 'http://localhost:' + grunt.config.get('ink.test.connect_port') + '/' + testFile;
            var displayName = path.basename(path.dirname(testFile));

            console.log('\nrunning tests for ' + testFile);
            console.log('(visiting ' + url + ')');
            phantomjsProcess = child_process.spawn('./node_modules/phantomjs/bin/phantomjs', [
                    'test/phantomjs-qunit.js',
                    url
                ]);
            phantomjsProcess.on('close', function(exitCode) {
                if (exitCode) {
                    failures.push(displayName);
                }
                next(null);
            });
            phantomjsProcess.stdout.pipe(process.stdout);
            phantomjsProcess.stderr.pipe(process.stdout);
        }, function afterAllTests() {
            if (failures.length) {
                console.log('\n# %d suites (in %d) FAILED: %s',
                    failures.length, testFiles.length, failures.join(' ,'));
                process.exit(failures.length);
            } else {
                console.log('\n# %d suites passed', testFiles.length);
            }
            done(failures.length);
        });
    });
	grunt.registerTask('test', function (moduleName) {
        if (moduleName) {
            grunt.config.set('_phantomjs.options.module', moduleName);
        }
        grunt.task.run(['connect:test', '_phantomjs:test']);
    });
    grunt.registerTask('custom_bundle', 'Create your custom bundle from a json file', function (fileName) {
        if (arguments.length === 0) {
            grunt.log.error('You need to specify a file name');
        }

        var bundle = grunt.file.readJSON(fileName);
        var dependencies = bundle.dependencies || [];
        grunt.config.set('concat.ink_custom', {
            files: [{
                expand: true,
                flatten: true,
                cwd: '<%= ink.folders.js.src %>',
                dest: '<%= ink.folders.js.dist %>' + bundle.name + '/',
                src: dependencies.map(function (depName) {
                    return depName.replace('Ink/', '') + '/lib.js';
                }),
                rename: function (dest, src) {
                    return dest + 'ink-custom.js';
                }
            }]
        });
        grunt.config.set('uglify.ink_custom', {
            src: '<%= ink.folders.js.dist %>' + bundle.name + '/' + 'ink-custom.js',
            dest: '<%= ink.folders.js.dist %>' + bundle.name + '/' + 'ink-custom.min.js'
        });
        grunt.task.run(['concat:ink_custom', 'uglify:ink_custom']);
    });
};
<commit_msg>minify autoload.js too<commit_after>module.exports = function (grunt) {
    var child_process = require('child_process');
    var path = require('path');
    var async = require('async');

    require('jit-grunt')(grunt, {
        'bower': 'grunt-bower-task',
    });

    var jshintFile = './src/js/.jshintrc';

    // Folder containing the Ink source files, Ink/*
    // (Relative to your "js" folder containing ink-all.js)
    // for source maps.
    // If you're serving the whole Ink tree on your server, the below works.
    var sourceMapPathToInkSource = '../../src/js';

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        ink: {
            folders: {
                bower: './bower_components/',
                js: {
                    srcBase: './src/js/',
                    src: './src/js/Ink/',
                    tests: './src/js/tests/',
                    dist: './dist/js/'
                },
                css: {
                    src: './src/sass/',
                    dist: './dist/css/'
                }
            },
            test: {
                connect_port: process.env['INK_TEST_CONNECT_PORT'] || 8000,
                root: '.',
            }
        },
        // handle 3rd party dependencies
        bower: {
            install: {
                options: {
                    copy: false,
                    targetDir: '<%= ink.folders.bower %>',
                    layout: 'byType',
                    install: true,
                    verbose: false,
                    cleanTargetDir: false
                }
            }
        },
        copy: {
            fontAwesome: {
                files: [
                    {
                        cwd: '<%= ink.folders.bower %>font-awesome/scss/',
                        src: '*.scss',
                        dest: 'src/sass/contrib/font-awesome/',
                        expand: true,
                    }
                ]
            },
            animate: {
                files: [{
                    cwd: '<%= ink.folders.bower %>animate.css',
                    src: ['animate.css'],
                    dest: 'src/sass/contrib/animations/',
                    expand: true,
                    rename: function (dest, src) {
                        return dest + 'animate.css';
                    }
                }]
            },
            modernizr: {
                files: [{
                    cwd: '<%= ink.folders.bower %>modernizr',
                    src: 'modernizr.js',
                    dest: '<%= ink.folders.js.dist %>',
                    expand: true
                }]
            },

            compass: {
                files: [
                    {
                        cwd: '<%= ink.folders.bower %>bower-compass-core/compass/stylesheets/',
                        src: '**/*.scss',
                        dest: 'src/sass/contrib/',
                        expand: true,
                    }
                ]
            },
            facss: {
              src: 'dist/css/contrib/font-awesome/font-awesome.css',
              dest: 'dist/css/font-awesome.css'
            }
        },

        // builds the javascript bundles
        concat: {

            // ink.js
            ink: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>',
                    src: [
                        '1/**/lib.js',
                        'Net/**/lib.js',
                        'Dom/**/lib.js',
                        'Util/**/lib.js',
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink.js';
                    }
                }]
            },

            // ink-all.js
            ink_all: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>',
                    src: [
                        '1/**/lib.js',
                        // Don't include autoload
                        'Net/**/lib.js',
                        'Dom/**/lib.js',
                        'Util/**/lib.js',
                        'UI/**/lib.js'
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink-all.js';
                    }
                }]
            },

            // ink-ui.js
            ink_ui: {
                files: [{
                    expand: true,
                    flatten: true,
                    cwd: '<%= ink.folders.js.src %>UI/',
                    src: [
                        '**/lib.js'
                    ],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        return dest + 'ink-ui.js';
                    }
                }]
            },

            // ui components as single files
            ui: {
                files: [{
                    expand: true,
                    cwd: '<%= ink.folders.js.src %>UI/',
                    src: ['**/[0-9]/lib.js'],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        // check if this is v1
                        // Here data is in the form of [UIComponent]/[ver]/lib.js
                        var split = src.split(/\//);
                        var modName = split[0].toLowerCase();
                        var version = split[1];

                        if (version === '1') {
                            // and it it is discard the version number
                            return dest + 'ink.' + modName + '.js';
                        } else {
                            // or replace the slash by an underscore and version number and prepend to dest file name
                            return dest + 'ink.' + modName + '-' + version + '.js';
                        }
                    }
                }
                ]
            },

            autoload: {
                files: [{
                    expand: true,
                    cwd: '<%= ink.folders.js.src %>Autoload',
                    src: ['**/lib.js'],
                    dest: '<%= ink.folders.js.dist %>',
                    rename: function (dest, src) {
                        var version = src.split('/')[0];
                        if (version === '1') {
                            return dest + 'autoload.js';
                        } else {
                            return dest + 'autoload-' + version + '.js';
                        }
                    }
                }]
            }
        },

        clean: {
            js: {
                src: [
                    '<%= ink.folders.js.dist %>/ink*.js',
                    '<%= ink.folders.js.dist %>/ink*.js.map',
                ]
            },
            css: {
                src: [
                  '<%= ink.folders.css.dist %>/*.css',
                  '<%= ink.folders.css.dist %>/*.css.map',
                  '!<%= ink.folders.css.dist %>/quick-start.css'
                ]
            },
            csscontrib: [ '<%= ink.folders.css.dist %>/contrib' ]
        },

        // CONCATENATE JS
        uglify: {
            options: {
                report: 'min',
                sourceMapIncludeSources: true,
                compress: {
                    sequences: true,
                    properties: true,
                    dead_code: false,
                    drop_debugger: false,
                    unsafe: false,
                    conditionals: true,
                    comparisons: true,
                    evaluate: true,
                    booleans: true,
                    loops: true,
                    unused: false,
                    hoist_funs: true,
                    hoist_vars: false,
                    if_return: true,
                    join_vars: true,
                    cascade: true
                }
            },
            ink: {
                src: [
                    '<%= ink.folders.js.src %>1/**/lib.js',
                    '<%= ink.folders.js.src %>Net/**/lib.js',
                    '<%= ink.folders.js.src %>Dom/**/lib.js',
                    '<%= ink.folders.js.src %>Util/**/lib.js',
                ],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink.js.map',
                    sourceMappingURL: 'ink.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink.min.js'
            },
            ink_all: {
                src: [
                    '<%= ink.folders.js.src %>1/**/lib.js',
                    // Do not include autoload
                    '<%= ink.folders.js.src %>Net/**/lib.js',
                    '<%= ink.folders.js.src %>Dom/**/lib.js',
                    '<%= ink.folders.js.src %>UI/**/lib.js',
                    '<%= ink.folders.js.src %>Util/**/lib.js',
                ],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink-all.js.map',
                    sourceMappingURL: 'ink-all.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink-all.min.js'
            },
            ink_ui: {
                src: ['<%= ink.folders.js.src %>UI/**/lib.js'],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>ink-ui.js.map',
                    sourceMappingURL: 'ink-ui.js.map'
                },
                dest: '<%= ink.folders.js.dist %>ink-ui.min.js'
            },
            autoload: {
                src: ['<%= ink.folders.js.src %>Autoload/1/lib.js'],
                options: {
                    sourceMap: '<%= ink.folders.js.dist %>autoload.js.map',
                    sourceMappingURL: 'autoload.js.map'
                },
                dest: '<%= ink.folders.js.dist %>autoload.min.js'
            }
        },

        // Runs JSHint on the Ink.js JavaScript source
        jshint: {
            inkjs: {
                options: {
                    jshintrc: '<%= ink.folders.js.srcBase %>.jshintrc'
                },
                files: {
                    src: '<%= ink.folders.js.src %>**/lib.js'
                }
            },
        },

        compass: {
            css: {
                options: {
                    outputStyle: 'expanded',
                    noLineComments: true,
                    relativeAssets: true,
                    sassDir: 'src/sass',
                    cssDir: "dist/css",
                    fontsDir: 'dist/fonts',
                    imagesDir: 'dist/img'
                }
            },
        },

        cssmin: {
            minify: {
                expand: true,
                cwd: '<%= ink.folders.css.dist %>',
                src: ['*.css', '!quick-start.css', '!*min*'],
                dest: '<%= ink.folders.css.dist %>',
                ext: '.min.css',
                options: {
                    keepSpecialComments: 0,
                    report: 'min',
                    sourceMap: true,
                    sourceMapFilename: '<%= ink.folders.css.dist %>ink-min.css.map',
                    sourceMapRootpath: '../../'
                }
            }
        },

        connect: {
            test: {
                options: {
                    port: '<%= ink.test.connect_port %>',
                    base: '<%= ink.test.root %>',
                    keepalive: false
                }
            },
        },

        // Creates a plato report
        plato: {
            inkjs: {
                options: {
                    jshint: grunt.file.readJSON(jshintFile, {
                        encoding: 'utf-8'
                    })
                },
                files: {
                    '<%= ink.folders.js.srcBase %>report': '<%= ink.folders.js.src %>**/lib.js'
                }
            }
        },

        watch: {
            css: {
                files: [
                    'src/**/*.scss'
                ],
                tasks: ['css'],
                options: {
                    spawn: false,
                    interrupt: true,
                }
            },
            js: {
                files: ['<%= ink.folders.js.src %>/**/*.js'],
                tasks: ['js'],
                options: {
                    spawn: false,
                    interrupt: true,
                }
            },
        },

        compress: {
          main: {
            options: {
              archive: 'ink-<%= pkg.version %>.zip',
              mode: "zip",
              level: 9,
              pretty: true
            },
            files: [
              {expand: true, cwd: "dist/", src: ['**'], dest: '/ink-<%= pkg.version %>'} // includes files in path and its subdirs
            ]
          }
        },

        bump : {
            options: {
                files: [ 'bower.json', 'package.json', '<%= ink.folders.js.src %>/1/lib.js'],
                push: false,
                commit: false,
                tagName: '%VERSION%',
                createTag: false,
                commitFiles: []
            }
        }
    });

    grunt.registerTask('js', ['clean:js', 'concat', 'uglify']);
    grunt.registerTask('css', ['clean:css', 'compass', 'copy:facss', 'clean:csscontrib', 'cssmin']);
    grunt.registerTask('dist', ['css', 'js', 'compress']);
    grunt.registerTask('dependencies', ['bower', 'copy:fontAwesome', 'copy:compass']);
    grunt.registerTask('default', ['dependencies','css','js']);
    grunt.registerTask('_phantomjs', function (module) {
        this.requires('connect:test');

        var options = this.options({
            module: '**'
        });

        var failures = [];

        var testFiles = grunt.file.expand('test/unit/' + options.module + '/index.html');

        var done = this.async();

        async.eachSeries(testFiles, function (testFile, next) {
            var url = 'http://localhost:' + grunt.config.get('ink.test.connect_port') + '/' + testFile;
            var displayName = path.basename(path.dirname(testFile));

            console.log('\nrunning tests for ' + testFile);
            console.log('(visiting ' + url + ')');
            phantomjsProcess = child_process.spawn('./node_modules/phantomjs/bin/phantomjs', [
                    'test/phantomjs-qunit.js',
                    url
                ]);
            phantomjsProcess.on('close', function(exitCode) {
                if (exitCode) {
                    failures.push(displayName);
                }
                next(null);
            });
            phantomjsProcess.stdout.pipe(process.stdout);
            phantomjsProcess.stderr.pipe(process.stdout);
        }, function afterAllTests() {
            if (failures.length) {
                console.log('\n# %d suites (in %d) FAILED: %s',
                    failures.length, testFiles.length, failures.join(' ,'));
                process.exit(failures.length);
            } else {
                console.log('\n# %d suites passed', testFiles.length);
            }
            done(failures.length);
        });
    });
	grunt.registerTask('test', function (moduleName) {
        if (moduleName) {
            grunt.config.set('_phantomjs.options.module', moduleName);
        }
        grunt.task.run(['connect:test', '_phantomjs:test']);
    });
    grunt.registerTask('custom_bundle', 'Create your custom bundle from a json file', function (fileName) {
        if (arguments.length === 0) {
            grunt.log.error('You need to specify a file name');
        }

        var bundle = grunt.file.readJSON(fileName);
        var dependencies = bundle.dependencies || [];
        grunt.config.set('concat.ink_custom', {
            files: [{
                expand: true,
                flatten: true,
                cwd: '<%= ink.folders.js.src %>',
                dest: '<%= ink.folders.js.dist %>' + bundle.name + '/',
                src: dependencies.map(function (depName) {
                    return depName.replace('Ink/', '') + '/lib.js';
                }),
                rename: function (dest, src) {
                    return dest + 'ink-custom.js';
                }
            }]
        });
        grunt.config.set('uglify.ink_custom', {
            src: '<%= ink.folders.js.dist %>' + bundle.name + '/' + 'ink-custom.js',
            dest: '<%= ink.folders.js.dist %>' + bundle.name + '/' + 'ink-custom.min.js'
        });
        grunt.task.run(['concat:ink_custom', 'uglify:ink_custom']);
    });
};
<|endoftext|>


<commit_before>var request = require('request');

var safari_browsers = [
	{
		browserName: 'safari',
		platform: 'OS X 10.10',
		version: '8.0'
	}
];

var chrome_browsers = [
	{
		browserName: 'chrome',
		platform: 'OS X 10.10',
		version: '44.0'
	},
	{
		browserName: 'chrome',
		platform: 'Windows 10',
		version: '43.0'
	},
	{
		browserName: 'chrome',
		platform: 'Linux',
		version: '42.0'
	}
];

var firefox_browsers = [
	{
		browserName: 'firefox',
		platform: 'Windows 10',
		version: '40.0'
	},
	{
		browserName: 'firefox',
		platform: 'OS X 10.10',
		version: '39.0'
	},
	{
		browserName: 'firefox',
		platform: 'Linux',
		version: '38.0'
	}
];

var ios_browsers = [
	{
		browserName: 'iphone',
		deviceName: 'iPhone Simulator',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '8.4'
	}
];

var android_browsers = [
	{
		browserName: 'android',
		deviceName: 'Android Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '5.1'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7 HD Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.4'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7C Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.3'
	},
	{
		browserName: 'android',
		deviceName: 'LG Nexus 4 Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.2'
	},
	{
		browserName: 'android',
		deviceName: 'HTC One X Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.1'
	},
	{
		browserName: 'android',
		deviceName: 'HTC Evo 3D Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.0'
	}
];

var ie_browsers = [
	{
		browserName: 'internet explorer',
		platform: 'Windows 10',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 8.1',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 7',
		version: '10.0'
	}
];

var test_urls = [
	'http://0.0.0.0:9999/test/test.html',
	'http://0.0.0.0:9999/test/integration-test.html'
];

module.exports = function(grunt) {
	grunt.initConfig({
		'saucelabs-mocha': {
			all: {
				options: {
					username: 'branchmetrics',
					urls: test_urls,
					maxRetries: 3,
					testname: 'Web SDK Tests',
					browsers: [].concat(
						safari_browsers,
						chrome_browsers,
						// firefox_browsers,
						android_browsers,
						ios_browsers,
						ie_browsers)
				}
			},
			options: {
				force: true
			}
		},
		connect: {
			server: {
				options: {
					port: 9999,
					base: ''
				}
			}
		}
	});

	// Loading dependencies
	for (var key in grunt.file.readJSON("package.json").devDependencies) {
		if (key !== "grunt" && key.indexOf("grunt") === 0) {
			grunt.loadNpmTasks(key);
		}
	}

	grunt.loadNpmTasks('grunt-saucelabs');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('test', ['connect', 'saucelabs-mocha']);
};
<commit_msg>updates to saucelabs testing config in an attempt to fix reported iOS errors<commit_after>var request = require('request');

var safari_browsers = [
	{
		browserName: 'safari',
		platform: 'OS X 10.10',
		version: '8.0'
	}
];

var chrome_browsers = [
	{
		browserName: 'chrome',
		platform: 'OS X 10.10',
		version: '44.0'
	},
	{
		browserName: 'chrome',
		platform: 'Windows 10',
		version: '43.0'
	},
	{
		browserName: 'chrome',
		platform: 'Linux',
		version: '42.0'
	}
];

var firefox_browsers = [
	{
		browserName: 'firefox',
		platform: 'Windows 10',
		version: '40.0'
	},
	{
		browserName: 'firefox',
		platform: 'OS X 10.10',
		version: '39.0'
	},
	{
		browserName: 'firefox',
		platform: 'Linux',
		version: '38.0'
	}
];

var ios_browsers = [
	{
		browserName: 'iphone',
		deviceName: 'iPhone 6',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '9.0'
	},
	{
		browserName: 'iphone',
		deviceName: 'iPhone 6',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '9.1'
	},
	{
		browserName: 'iphone',
		deviceName: 'iPhone 6',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '9.2'
	}
];

var android_browsers = [
	{
		browserName: 'android',
		deviceName: 'Android Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '5.1'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7 HD Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.4'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7C Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.3'
	},
	{
		browserName: 'android',
		deviceName: 'LG Nexus 4 Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.2'
	},
	{
		browserName: 'android',
		deviceName: 'HTC One X Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.1'
	},
	{
		browserName: 'android',
		deviceName: 'HTC Evo 3D Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.0'
	}
];

var ie_browsers = [
	{
		browserName: 'internet explorer',
		platform: 'Windows 10',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 8.1',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 7',
		version: '10.0'
	}
];

var test_urls = [
	'http://0.0.0.0:9999/test/test.html',
	'http://0.0.0.0:9999/test/integration-test.html'
];

module.exports = function(grunt) {
	grunt.initConfig({
		'saucelabs-mocha': {
			all: {
				options: {
					username: 'branchmetrics',
					urls: test_urls,
					maxRetries: 3,
					testname: 'Web SDK Tests',
					browsers: [].concat(
						safari_browsers,
						chrome_browsers,
						// firefox_browsers,
						android_browsers,
						ios_browsers,
						ie_browsers)
				}
			},
			options: {
				force: true
			}
		},
		connect: {
			server: {
				options: {
					port: 9999,
					base: ''
				}
			}
		}
	});

	// Loading dependencies
	for (var key in grunt.file.readJSON("package.json").devDependencies) {
		if (key !== "grunt" && key.indexOf("grunt") === 0) {
			grunt.loadNpmTasks(key);
		}
	}

	grunt.loadNpmTasks('grunt-saucelabs');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('test', ['connect', 'saucelabs-mocha']);
};
<|endoftext|>


<commit_before>"use strict";

module.exports = function(grunt){
  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),

    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        es5: true,
        esnext: true,
        globalstrict: true,
        immed: true,
        indent: 2,
        lastsemic: true,
        latedef: true,
        newcap: true,
        noarg: true,
        node: true,
        nonew: true,
        undef: true,
        unused: true,
        quotmark: true,
        strict: true,
        trailing: true,
        white: false
      },

      gruntfile: ["Gruntfile.js"],
      lib: ["index.js", "lib/**/*.js"],

      tests: {
        options: {
          globals: {
            describe: true,
            specify: true
          }
        },

        files: {
          src: ["tests/**/*.js"]
        }
      }
    }
  });

  grunt.loadNpmTasks("grunt-contrib-jshint");
};
<commit_msg>Add 'setImmediate' to JSHint globals<commit_after>"use strict";

module.exports = function(grunt){
  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),

    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        es5: true,
        esnext: true,
        globalstrict: true,
        immed: true,
        indent: 2,
        lastsemic: true,
        latedef: true,
        newcap: true,
        noarg: true,
        node: true,
        nonew: true,
        undef: true,
        unused: true,
        quotmark: true,
        strict: true,
        trailing: true,
        white: false
      },

      gruntfile: ["Gruntfile.js"],
      lib: ["index.js", "lib/**/*.js"],

      tests: {
        options: {
          globals: {
            describe: true,
            specify: true,
            setImmediate: true
          }
        },

        files: {
          src: ["tests/**/*.js"]
        }
      }
    }
  });

  grunt.loadNpmTasks("grunt-contrib-jshint");
};
<|endoftext|>


<commit_before>/* jshint node: true */
var _ = require('lodash');
var path = require('path');

module.exports = function(grunt) {

  var NW_VERSION = '0.10.4';
  var BUILD_DIR = 'build';
  var BUILD_TARGETS = {
    linux_ia32: true,
    linux_x64: true,
    win: true,
    osx: false
  };
  var PKG = grunt.file.readJSON('package.json');
  var PKG_OVERWRITE = {
    window: {
      toolbar: false
    }
  };

  // Create build tasks options
  var buildOptions = _.merge({
    runtimeVersion: NW_VERSION
  }, BUILD_TARGETS);

  // Define copy:build tasks files
  var snapFiles = [];
  _(BUILD_TARGETS).forEach(function(isEnabled, target) {
    if(isEnabled) {
      var arch = 'ia32';
      var platform = target;
      if(platform.indexOf('linux') !== -1) {
        arch = platform.split('_')[1];
        platform = 'linux';
      }
      var dirName = PKG.name + '-' + PKG.version + '-' + platform + '-' + arch;
      var destPath = path.join(BUILD_DIR, dirName + '/');

      // Add apps to build
      snapFiles.push({src: 'apps/**', dest: destPath});

      // Add snap dependencies
      var modules = _.keys(PKG.dependencies).map(function(moduleName) {
        return path.join('node_modules', moduleName, '**');
      });
      snapFiles.push({src: modules, dest: destPath});

      // Add package.json
      snapFiles.push({src: 'package.json', dest: destPath});

      // Add main files, licence, & config
      snapFiles.push({
        src: ['index.html', 'app.js', 'config/defaults.yaml', 'LICENSE'],
        dest: destPath}
      );

    }
  });

  // Configure tasks
  grunt.initConfig({

    pkg: PKG,

    download: {
      options: {
        runtimeVersion: NW_VERSION
      }
    },

    run: {
      options: {
        nwArgs: ['.'],
        runtimeVersion: NW_VERSION
      }
    },

    build: {
      options: buildOptions
    },

    clean: {
      build: [BUILD_DIR]
    },

    copy: {
      build: {
        files: snapFiles,
        options: {
          noProcess: ['**','!package.json'],
          process: function() {
            var pkg = _.merge(PKG, PKG_OVERWRITE);
            return JSON.stringify(pkg, null, 2);
          }
        }
      }
    }

  });

  grunt.registerTask('snap:run',  ['download', 'run']);
  grunt.registerTask(
    'snap:build',
    ['download', 'clean:build', 'build', 'copy:build']
  );
  grunt.registerTask('default', ['snap:run']);

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-nw');

};
<commit_msg>Fix bug build process<commit_after>/* jshint node: true */
var _ = require('lodash');
var path = require('path');

module.exports = function(grunt) {

  var NW_VERSION = '0.10.4';
  var BUILD_DIR = 'build';
  var BUILD_TARGETS = {
    linux_ia32: false,
    linux_x64: true,
    win: false,
    osx: false
  };
  var PKG = grunt.file.readJSON('package.json');
  var PKG_OVERWRITE = {
    window: {
      toolbar: false
    }
  };

  // Create build tasks options
  var buildOptions = _.merge({
    runtimeVersion: NW_VERSION
  }, BUILD_TARGETS);

  // Define copy:build tasks files
  var snapFiles = [];
  _(BUILD_TARGETS).forEach(function(isEnabled, target) {
    if(isEnabled) {
      var arch = 'ia32';
      var platform = target;
      if(platform.indexOf('linux') !== -1) {
        arch = platform.split('_')[1];
        platform = 'linux';
      }
      var dirName = PKG.name + '-' + PKG.version + '-' + platform + '-' + arch;
      var destPath = path.join(BUILD_DIR, dirName + '/');

      // Add lib
      snapFiles.push({src: 'lib/**', dest: destPath});

      // Add themes
      snapFiles.push({src: 'themes/**', dest: destPath});

      // Add apps to build
      snapFiles.push({src: 'apps/**', dest: destPath});

      // Add snap dependencies
      var modules = _.keys(PKG.dependencies).map(function(moduleName) {
        return path.join('node_modules', moduleName, '**');
      });
      snapFiles.push({src: modules, dest: destPath});

      // Add package.json
      snapFiles.push({src: 'package.json', dest: destPath});

      // Add main files, licence, & config
      snapFiles.push({
        src: ['index.html', 'app.js', 'config/defaults.yaml', 'LICENSE'],
        dest: destPath}
      );

    }
  });

  // Configure tasks
  grunt.initConfig({

    pkg: PKG,

    download: {
      options: {
        runtimeVersion: NW_VERSION
      }
    },

    run: {
      options: {
        nwArgs: ['.'],
        runtimeVersion: NW_VERSION
      }
    },

    build: {
      options: buildOptions
    },

    clean: {
      build: [BUILD_DIR]
    },

    copy: {
      build: {
        files: snapFiles,
        options: {
          noProcess: ['**','!package.json'],
          process: function() {
            var pkg = _.merge(PKG, PKG_OVERWRITE);
            return JSON.stringify(pkg, null, 2);
          }
        }
      }
    }

  });

  grunt.registerTask('snap:run',  ['download', 'run']);
  grunt.registerTask(
    'snap:build',
    ['download', 'clean:build', 'build', 'copy:build']
  );
  grunt.registerTask('default', ['snap:run']);

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-nw');

};
<|endoftext|>


<commit_before>// Generated on 2014-06-12 using generator-angular 0.9.0-1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

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

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

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

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

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

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

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

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

    // 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 app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath: new RegExp('^<%= yeoman.app %>/|../')
      },
      sass: {
      src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
      ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

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

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

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

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

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

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

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ngmin tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

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

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

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

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

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

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

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

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>Mods for grunt serve to work on Nitrous.io<commit_after>// Generated on 2014-06-12 using generator-angular 0.9.0-1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

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

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

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

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

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

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

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

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

    // 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 app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath: new RegExp('^<%= yeoman.app %>/|../')
      },
      sass: {
      src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
      ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

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

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

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

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

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

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

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ngmin tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

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

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

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

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

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

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

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

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


<commit_before>'use strict';

function key_watch(grunt) {
  var keypress = require('keypress');
  var stdin = process.openStdin();
  var touch = require('touch');

  // make `process.stdin` begin emitting "keypress" events
  keypress(process.stdin);

  // listen for the "keypress" event
  process.stdin.on('keypress', function (ch, key) {
    if (key) {
      if (key.ctrl && key.name == 'c') {
        process.stdin.pause();
        return process.exit();
      } else if(key.name == "c") {
        process.stdout.write('\u001B[2J\u001B[0;0f');
      } else if(key.name == "r") {
        // Reload
        touch(__filename);
      }
    }
  });

  process.stdin.setRawMode(true);
  process.stdin.resume();
}

module.exports = function(grunt) {
  // Test options
  var test_task = grunt.option('test') || "test";
  var test_grep = grunt.option('grep') || null;
  if (test_grep != null) {
    test_task = "slow_test";
  }

  // Lib path
  var lib = process.env.AZK_LIB_PATH || "lib";

  // Project configuration.
  grunt.initConfig({
    // ENV's
    env: {
      test: {
        NODE_ENV: "test",
      }
    },

    // Configuration to be run (and then tested).
    traceur: {
      options: {
        sourceMaps: true,
        modules: 'commonjs'
      },
      source: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js', '!share/*.js'],
          dest: lib + '/azk/',
          ext: '.js'
        }]
      },
      spec: {
        files: [{
          expand: true,
          cwd: 'spec/',
          src: '**/*.js',
          dest: lib + '/spec/',
          ext: '.js'
        }]
      }
    },

    'node-inspector': {
      dev: {}
    },

    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          timeout: 5000,
          grep: "@slow",
          invert: true,
        },
        src: [lib + '/spec/**/*_spec.js']
      },

      slow_test: {
        options: {
          reporter: 'spec',
          timeout: 50000,
          grep: test_grep,
        },
        src: [lib + 'spec/**/*_spec.js']
      }
    },

    watch: {
      spec: {
        files: [
          'Gruntfile.js',
          'src/**/*.js',
          'spec/**/*.js',
        ],
        tasks: [test_task]
      },

      traceur: {
        files: [
          'Gruntfile.js',
          'src/**/*.js',
          'spec/**/*.js',
        ],
        tasks: ['clear', 'newer:traceur']
      }
    },
  });

  // load all grunt tasks matching the `grunt-*` pattern
  require('load-grunt-tasks')(grunt);

  // Clear task
  grunt.registerTask('clear', function() {
    process.stdout.write('\u001B[2J\u001B[0;0f');
  });

  grunt.registerTask('test', ['env:test', 'clear', 'newer:traceur', 'mochaTest:test']);
  grunt.registerTask('slow_test', ['env:test', 'clear', 'newer:traceur', 'mochaTest:slow_test']);
  grunt.registerTask('compile', ['clear', 'newer:traceur', 'watch:traceur']);
  grunt.registerTask('inspector', ["node-inspector"]);
  grunt.registerTask('default', function() {
    key_watch(grunt);
    return grunt.task.run([test_task, 'watch:spec']);
  });
};
<commit_msg>Fixing test paths in Gruntfile.<commit_after>'use strict';

function key_watch(grunt) {
  var keypress = require('keypress');
  var stdin = process.openStdin();
  var touch = require('touch');

  // make `process.stdin` begin emitting "keypress" events
  keypress(process.stdin);

  // listen for the "keypress" event
  process.stdin.on('keypress', function (ch, key) {
    if (key) {
      if (key.ctrl && key.name == 'c') {
        process.stdin.pause();
        return process.exit();
      } else if(key.name == "c") {
        process.stdout.write('\u001B[2J\u001B[0;0f');
      } else if(key.name == "r") {
        // Reload
        touch(__filename);
      }
    }
  });

  process.stdin.setRawMode(true);
  process.stdin.resume();
}

module.exports = function(grunt) {
  // Test options
  var test_task = grunt.option('test') || "test";
  var test_grep = grunt.option('grep') || null;
  if (test_grep != null) {
    test_task = "slow_test";
  }

  // Lib path
  var lib = process.env.AZK_LIB_PATH || "lib";

  // Project configuration.
  grunt.initConfig({
    // ENV's
    env: {
      test: {
        NODE_ENV: "test",
      }
    },

    // Configuration to be run (and then tested).
    traceur: {
      options: {
        sourceMaps: true,
        modules: 'commonjs'
      },
      source: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js', '!share/*.js'],
          dest: lib + '/azk/',
          ext: '.js'
        }]
      },
      spec: {
        files: [{
          expand: true,
          cwd: 'spec/',
          src: '**/*.js',
          dest: lib + '/spec/',
          ext: '.js'
        }]
      }
    },

    'node-inspector': {
      dev: {}
    },

    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          timeout: 5000,
          grep: "@slow",
          invert: true,
        },
        src: [lib + '/spec/**/*_spec.js']
      },

      slow_test: {
        options: {
          reporter: 'spec',
          timeout: 50000,
          grep: test_grep,
        },
        src: [lib + '/spec/**/*_spec.js']
      }
    },

    watch: {
      spec: {
        files: [
          'Gruntfile.js',
          'src/**/*.js',
          'spec/**/*.js',
        ],
        tasks: [test_task]
      },

      traceur: {
        files: [
          'Gruntfile.js',
          'src/**/*.js',
          'spec/**/*.js',
        ],
        tasks: ['clear', 'newer:traceur']
      }
    },
  });

  // load all grunt tasks matching the `grunt-*` pattern
  require('load-grunt-tasks')(grunt);

  // Clear task
  grunt.registerTask('clear', function() {
    process.stdout.write('\u001B[2J\u001B[0;0f');
  });

  grunt.registerTask('test', ['env:test', 'clear', 'newer:traceur', 'mochaTest:test']);
  grunt.registerTask('slow_test', ['env:test', 'clear', 'newer:traceur', 'mochaTest:slow_test']);
  grunt.registerTask('compile', ['clear', 'newer:traceur', 'watch:traceur']);
  grunt.registerTask('inspector', ["node-inspector"]);
  grunt.registerTask('default', function() {
    key_watch(grunt);
    return grunt.task.run([test_task, 'watch:spec']);
  });
};
<|endoftext|>


<commit_before>/**
 * Breve.js - A McGyver toolbox of small bits to speed up vanilla js development / prototyping
 *
 * @url https://github.com/barbaracassani/brevejs
 *
 * Features: mixing and inheritance, custom events, uuid, debounce and throttle, and, as a pure flight of
 * fancy, a polyfill for requestAnimationFrame. It's intentionally basic and conceived for convenience and speed,
 * not abundance of features.
 *
 * @author barbara [at] kitsch-en [net]
 */

(function(global, factory) {

    'use strict';

    if (typeof exports !== 'undefined') {

        // CommonJS
        exports.Breve = factory();

    } else if (typeof define === 'function' && define.amd) {

        // Require.js, Almond.js
        define('breve-js', [], function() {
            return factory();
        });

    } else {

        global.Breve = factory();

    }

}(this, function() {

    var BR =  {};

    /**
     * A bog standard mixin
     * Expects receiver + methods as arguments
     */
    BR.mixin = function() {
        if (arguments.length < 2) {
            throw Error("This mixin expect at least 3 arguments, receiver and augmentator, and a method name");
        }

        var args = Array.prototype.slice.apply(arguments),
            target = args.shift(),
            source = args.shift(),
            methodNames = args,
            len = methodNames.length - 1;

        while(len >= 0) {
            target[methodNames[len]] = source[methodNames[len]];
            len--;
        }
    };

    /**
     * Extend method. If no child is supplied, one will be created
     * @param [optional] childObj
     * @param parentObj
     */
    BR.extend = function (childObj, parentObj) {

        var child, parent;

        if (!arguments.length) {
            throw Error("Extend expect at least 1 argument");
        }

        if (arguments.length === 1) {
            parent = arguments[0];
            child = function(){}
        } else {
            parent = parentObj;
            child = childObj;
        }

        var F = function() {};
        F.prototype = parent.prototype;

        child.prototype = new F();
        child.prototype.constructor = child;

        child.superclass = parent.prototype;
        if(parent.prototype.constructor == Object.prototype.constructor) {
            parent.prototype.constructor = parent;
        }
    };

    /**
     * Mixes in all the methods needed to transform an object into an observable
     * @param target
     */
    BR.makeObservable = function(target) {
        BR.mixin(target, this, 'publish', 'subscribe', 'unsubscribe', 'unsubscribeAll');
        return target;
    };

    //  helper function to create random hex numbers ( of length = 8 )
    var produceRandomHex = function() {
        var randomHex = (Math.random()).toString(16).substring(2,10);

        if(randomHex.length < 8){
            return randomHex + (Math.random()).toString(16).substring(2,3);
        } else {
            return randomHex;
        }
    }

    /**
     * Unique id
     * http://en.wikipedia.org/wiki/Universally_unique_identifier#Definition
     *
     * @returns {string}
     */
    BR.uuid = function() {
        //  create the random sequences
        var guid =
            produceRandomHex() + '-' +
            produceRandomHex() +
            produceRandomHex() +
            produceRandomHex();

        //  return the UUID with hyphens added
        return guid.substr(0,13) + '-' +
               guid.substr(12,4) + '-' +
               guid.substr(16,4) + '-' +
               guid.substr(20,12);
    };

    /**
     * Publishes events
     * @param event
     * @param args
     */
    BR.publish = function(event, args) {
        var callbacks,
            len,
            l, scope;

        this.listeners = this.listeners || {};
        callbacks = this.listeners[event];
        len = callbacks? callbacks.length : 0;

        if (!callbacks || !len) {
            return;
        }
        l = len-1;
        while (l >= 0) {
            scope = callbacks[l].scope || this;
            callbacks[l].callback.call(scope, args);
            l--;
        }
    };

    /**
     * Subscribes to an event. Returns a token that can be used to unsubscribe.
     * @param event
     * @param callback
     * @param scope
     * @returns {string}
     */
    BR.subscribe = function(event, callback, scope) {
        var listeners,
            token = BR.uuid('event');

        this.listeners = this.listeners || {};

        listeners = this.listeners;
        listeners[event] = listeners[event] || [];

        listeners[event].push({
            callback : callback,
            scope : scope,
            token : token
        });
        return token;
    };

    /**
     * Unsubscribe all the listeners
     * @param event
     */
    BR.unsubscribeAll = function(event) {
        if (event) {
            this.listeners[event] = [];
        } else {
            delete this.listeners;
        }
    };

    /**
     * Unsubscribe a single subscription. If called without the token, it will unsubscribe
     * everything for that event.
     * @param event
     * @param token
     */
    BR.unsubscribe = function(event, token) {

        var listeners,
            len;

        this.listeners = this.listeners || {};
        listeners = this.listeners;

        listeners[event] = listeners[event] || [];
        len = listeners[event].length;
        if (!token) {
            listeners[event] = [];
        }
        while (len >= 0) {
            if (token) {
                if (listeners[event][len].token === token) {
                    listeners[event].splice(len,1);
                    return;
                }
            }
            len--;
        }

    };

    BR.throttles = {};
    BR.debounces = {};

    /**
     * Throttles a function in order for it to be executed not too frequently.
     * @param id
     * @param func
     * @param scope
     * @param time
     * @param params
     */
    BR.throttle = function(id, func, scope, time, params) {
        if (BR.throttles[id]) {
            return;
        }
        func.call(scope, params);
        BR.throttles[id] = window.setTimeout(function() {
            window.clearTimeout(BR.throttles[id]);
            delete BR.throttles[id];
        }, time);
    };

    /**
     * Debounces a function for it to be executed after x time after the last call has elapsed
     * @param id
     * @param func
     * @param scope
     * @param time
     * @param params
     */
    BR.debounce = function (id, func, scope, time, params) {
        if (BR.debounces[id]) {
            window.clearTimeout(BR.debounces[id]);
        } else {
            BR.debounces.id = id;
        }
        window.setTimeout(function () {
            func.call(scope, params);
            delete BR.debounces[id];
        }, time);
    };

    /**
     * Stubbing the console when it's not around
     * @type {Function}
     */
    window.console = window.console || {};
    ['log', 'warn', 'error', 'assert', 'info', 'debug'].forEach(function(value, iterator) {
        !window.console[value] && (window.console[value] = function(){});
    });

    /**
     * Polyfill for requestAnimationFrame
     */
    window.requestAnimationFrame = (function(){
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            function( callback ){
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    window.cancelAnimationFrame = (function() {
        return window.cancelAnimationFrame ||
            window.webkitCancelRequestAnimationFrame ||
            window.mozCancelRequestAnimationFrame ||
            function(id) {
                window.clearTimeout(id);
            };
    })();

    return BR;

}));
<commit_msg>added comment and missing semicolon<commit_after>/**
 * Breve.js - A McGyver toolbox of small bits to speed up vanilla js development / prototyping
 *
 * @url https://github.com/barbaracassani/brevejs
 *
 * Features: mixing and inheritance, custom events, uuid, debounce and throttle, and, as a pure flight of
 * fancy, a polyfill for requestAnimationFrame. It's intentionally basic and conceived for convenience and speed,
 * not abundance of features.
 *
 * @author barbara [at] kitsch-en [net]
 */

(function(global, factory) {

    'use strict';

    if (typeof exports !== 'undefined') {

        // CommonJS
        exports.Breve = factory();

    } else if (typeof define === 'function' && define.amd) {

        // Require.js, Almond.js
        define('breve-js', [], function() {
            return factory();
        });

    } else {

        global.Breve = factory();

    }

}(this, function() {

    var BR =  {};

    /**
     * A bog standard mixin
     * Expects receiver + methods as arguments
     */
    BR.mixin = function() {
        if (arguments.length < 2) {
            throw Error("This mixin expect at least 3 arguments, receiver and augmentator, and a method name");
        }

        var args = Array.prototype.slice.apply(arguments),
            target = args.shift(),
            source = args.shift(),
            methodNames = args,
            len = methodNames.length - 1;

        while(len >= 0) {
            target[methodNames[len]] = source[methodNames[len]];
            len--;
        }
    };

    /**
     * Extend method. If no child is supplied, one will be created
     * @param [optional] childObj
     * @param parentObj
     */
    BR.extend = function (childObj, parentObj) {

        var child, parent;

        if (!arguments.length) {
            throw Error("Extend expect at least 1 argument");
        }

        if (arguments.length === 1) {
            parent = arguments[0];
            child = function(){}
        } else {
            parent = parentObj;
            child = childObj;
        }

        var F = function() {};
        F.prototype = parent.prototype;

        child.prototype = new F();
        child.prototype.constructor = child;

        child.superclass = parent.prototype;
        if(parent.prototype.constructor == Object.prototype.constructor) {
            parent.prototype.constructor = parent;
        }
    };

    /**
     * Mixes in all the methods needed to transform an object into an observable
     * @param target
     */
    BR.makeObservable = function(target) {
        BR.mixin(target, this, 'publish', 'subscribe', 'unsubscribe', 'unsubscribeAll');
        return target;
    };

    //  helper function to create random hex numbers ( of length = 8 )
    var produceRandomHex = function() {
        var randomHex = (Math.random()).toString(16).substring(2,10);

        if(randomHex.length < 8){
            return randomHex + (Math.random()).toString(16).substring(2,3);
        } else {
            return randomHex;
        }
    };

    /**
     * Unique id
     * http://en.wikipedia.org/wiki/Universally_unique_identifier#Definition
     *
     * @returns {string}
     */
    BR.uuid = function() {
        //  create the random sequences
        var guid =
            produceRandomHex() + '-' +
            produceRandomHex() +
            produceRandomHex() +
            produceRandomHex();

        //  return the UUID with hyphens added
        return guid.substr(0,13) + '-' +
               guid.substr(12,4) + '-' +
               guid.substr(16,4) + '-' +
               guid.substr(20,12);
    };

    /**
     * Publishes events
     * @param event
     * @param args
     */
    BR.publish = function(event, args) {
        var callbacks,
            len,
            l, scope;

        this.listeners = this.listeners || {};
        callbacks = this.listeners[event];
        len = callbacks? callbacks.length : 0;

        if (!callbacks || !len) {
            return;
        }
        l = len-1;
        while (l >= 0) {
            scope = callbacks[l].scope || this;
            callbacks[l].callback.call(scope, args);
            l--;
        }
    };

    /**
     * Subscribes to an event. Returns a token that can be used to unsubscribe.
     * @param event
     * @param callback
     * @param scope
     * @returns {string}
     */
    BR.subscribe = function(event, callback, scope) {
        var listeners,
            token = BR.uuid('event');

        this.listeners = this.listeners || {};

        listeners = this.listeners;
        listeners[event] = listeners[event] || [];

        listeners[event].push({
            callback : callback,
            scope : scope,
            token : token
        });
        return token;
    };

    /**
     * Unsubscribe all the listeners
     * @param event
     */
    BR.unsubscribeAll = function(event) {
        if (event) {
            this.listeners[event] = [];
        } else {
            delete this.listeners;
        }
    };

    /**
     * Unsubscribe a single subscription. If called without the token, it will unsubscribe
     * everything for that event.
     * @param event
     * @param token
     */
    BR.unsubscribe = function(event, token) {

        var listeners,
            len;

        this.listeners = this.listeners || {};
        listeners = this.listeners;

        listeners[event] = listeners[event] || [];
        len = listeners[event].length;
        if (!token) {
            listeners[event] = [];
        }
        while (len >= 0) {
            if (token) {
                if (listeners[event][len].token === token) {
                    listeners[event].splice(len,1);
                    return;
                }
            }
            len--;
        }

    };

    BR.throttles = {};
    BR.debounces = {};

    /**
     * Throttles a function in order for it to be executed not too frequently.
     * @param id
     * @param func
     * @param scope
     * @param time
     * @param params
     */
    BR.throttle = function(id, func, scope, time, params) {
        if (BR.throttles[id]) {
            return;
        }
        func.call(scope, params);
        BR.throttles[id] = window.setTimeout(function() {
            window.clearTimeout(BR.throttles[id]);
            delete BR.throttles[id];
        }, time);
    };

    /**
     * Debounces a function for it to be executed after x time after the last call has elapsed
     * @param id
     * @param func
     * @param scope
     * @param time
     * @param params
     */
    BR.debounce = function (id, func, scope, time, params) {
        if (BR.debounces[id]) {
            window.clearTimeout(BR.debounces[id]);
        } else {
            BR.debounces.id = id;
        }
        window.setTimeout(function () {
            func.call(scope, params);
            delete BR.debounces[id];
        }, time);
    };

    /**
     * Stubbing the console when it's not around
     * @type {Function}
     */
    window.console = window.console || {};
    ['log', 'warn', 'error', 'assert', 'info', 'debug'].forEach(function(value, iterator) {
        !window.console[value] && (window.console[value] = function(){});
    });

    /**
     * Polyfill for requestAnimationFrame
     */
    window.requestAnimationFrame = (function(){
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            function( callback ){
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    window.cancelAnimationFrame = (function() {
        return window.cancelAnimationFrame ||
            window.webkitCancelRequestAnimationFrame ||
            window.mozCancelRequestAnimationFrame ||
            function(id) {
                window.clearTimeout(id);
            };
    })();

    return BR;

}));
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    // Project configuration.
    grunt.initConfig({
        karma: {
            unit: {
                configFile: 'test/karma.conf.js'
            }
        },
        nodewebkit: {
            options: {
                    version: '0.11.4',
                    platforms: ['win', 'osx', 'linux32', 'linux64'],
                    buildDir: './release',               // Where the build version of my node-webkit app is saved
                    downloadUrl: 'http://dl.nwjs.io/'    // Temporary fix: NodeWebkit binaries are located at a new address
            },
            src: [                                       // Your node-webkit app source files
                './package.json',
                './index.html',
                './ui/**/*'
            ]
        },
        copy: {
            toApp: {
                files: [
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/linux64/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/linux32/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/win/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/osx/ls_seed.app/Contents/Resources/VERSION'
                    }
                ]
            }
        },
        clean: {
            build: [
                "./release"
            ]
        },
        bowerRequirejs: {
            main: {
                rjsConfig: 'ui/js/require-config.js',
                options: {
                    'exclude-dev': true
                }
            },
            test: {
                rjsConfig: 'test/main-test.js',
                options: {
                    baseUrl: './public/js'
                }
            }
        }
    });
    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-execute');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-bower-requirejs');

    // Automatically generates the file paths for both requirejs config files.
    // In the .bowerrc file, this task is set to run after installing new bower components.
    grunt.registerTask('updatePaths', ['bowerRequirejs:main', 'bowerRequirejs:test']);

    // Used by CD
    grunt.registerTask('build', ['clean','nodewebkit','copy:toApp']);   // The name is fixed. You can't change the name.

    // Unit testing
    grunt.registerTask('test', ['karma:unit']);
};
<commit_msg>rename public to ui in the bowerRequirejs grunt task<commit_after>module.exports = function (grunt) {
    // Project configuration.
    grunt.initConfig({
        karma: {
            unit: {
                configFile: 'test/karma.conf.js'
            }
        },
        nodewebkit: {
            options: {
                    version: '0.11.4',
                    platforms: ['win', 'osx', 'linux32', 'linux64'],
                    buildDir: './release',               // Where the build version of my node-webkit app is saved
                    downloadUrl: 'http://dl.nwjs.io/'    // Temporary fix: NodeWebkit binaries are located at a new address
            },
            src: [                                       // Your node-webkit app source files
                './package.json',
                './index.html',
                './ui/**/*'
            ]
        },
        copy: {
            toApp: {
                files: [
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/linux64/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/linux32/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/win/VERSION'
                    },
                    {
                        cwd: './',
                        src: ['VERSION'],
                        dest: './release/ls_seed/osx/ls_seed.app/Contents/Resources/VERSION'
                    }
                ]
            }
        },
        clean: {
            build: [
                "./release"
            ]
        },
        bowerRequirejs: {
            main: {
                rjsConfig: 'ui/js/require-config.js',
                options: {
                    'exclude-dev': true
                }
            },
            test: {
                rjsConfig: 'test/main-test.js',
                options: {
                    baseUrl: './ui/js'
                }
            }
        }
    });
    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-execute');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-bower-requirejs');

    // Automatically generates the file paths for both requirejs config files.
    // In the .bowerrc file, this task is set to run after installing new bower components.
    grunt.registerTask('updatePaths', ['bowerRequirejs:main', 'bowerRequirejs:test']);

    // Used by CD
    grunt.registerTask('build', ['clean','nodewebkit','copy:toApp']);   // The name is fixed. You can't change the name.

    // Unit testing
    grunt.registerTask('test', ['karma:unit']);
};
<|endoftext|>