<commit_before>/*!
 * Copyright 2014 Digital Services, University of Cambridge Licensed
 * under the Educational Community License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('lodash');
var fs = require('fs');
var util = require('util');
var vm = require('vm');

module.exports = function(grunt) {

    ///////////////////
    // CONFIGURATION //
    ///////////////////

    grunt.initConfig({
        'target': 'target',
        'clean': ['<%= target %>'],
        'exec': {
            'removeTarget': {
                'cmd': 'rm -rf <%= target %>/optimized/<%= target %>'
            }
        },
        'copy': {
            'main': {
                'files': [
                    {
                        'expand': true,
                        'src': [
                            '**',
                            '!<%= target %>/.*/**',
                            '!node_modules/**'
                        ],
                        'dest': '<%= target %>/original'
                    }
                ]
            }
        },
        'requirejs': {
            'optimize': {
                'options': {
                    'appDir': './',
                    'baseUrl': './shared',
                    'mainConfigFile': './shared/gh/api/gh.bootstrap.js',
                    'dir': '<%= target %>/optimized',
                    'optimize': 'uglify',
                    'preserveLicenseComments': false,
                    'optimizeCss': 'standard',
                    // TODO: Replace this with a saner value
                    // @see https://github.com/jrburke/r.js/pull/653
                    'cssImportIgnore': '//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,400,300,600,700&subset=latin,cyrillic-ext,latin-ext,greek-ext',
                    'inlineText': true,
                    'useStrict': false,
                    'pragmas': {},
                    'skipPragmas': false,
                    'skipModuleInsertion': false,
                    'modules': [{
                        'name': 'gh.core'
                    }],
                    'fileExclusionRegExp': /^(\.|apache|etc|node_modules|tools)/,
                    'logLevel': 2
                }
            }
        },
        'ver': {
            'gh': {
                'basedir': '<%= target %>/optimized',
                'phases': [

                    // 1. Hash all the vendor fonts
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/fonts'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/css',
                            ],
                            'includeExts': ['css']
                        })
                    },

                    // 2. Hash all the vendor CSS and JS
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/css',
                                '<%= target %>/optimized/shared/vendor/js'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/apps',
                                '<%= target %>/optimized/shared'
                            ],
                            'includeExts': ['html']
                        })
                    },

                    // 3. Hash the GH CSS and JS files
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/gh/**'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/apps',
                                '<%= target %>/optimized/shared'
                            ],
                            'includeExts': ['html']
                        })
                    }
                ],
                'version': '<%= target %>/optimized/hashes.json'
            }
        },
        'coveralls': {
            'gh': {
                'src': 'coverage/lcov.info',
                'options': {
                    'src': 'coverage/lcov.info'
                }
            }
        },
        'ghost': {
            'dist': {
                'filesSrc': [
                    'tests/casperjs/tests/*.js'
                ],
                // CasperJS test command options
                'options': {
                    // Specify the files to be included in each test
                    'includes': [
                        'tests/casperjs/util/include/gh.api.admin.js',
                        'tests/casperjs/util/include/gh.api.app.js',
                        'tests/casperjs/util/include/gh.api.authentication.js',
                        'tests/casperjs/util/include/gh.api.config.js',
                        'tests/casperjs/util/include/gh.api.event.js',
                        'tests/casperjs/util/include/gh.api.orgunit.js',
                        'tests/casperjs/util/include/gh.api.series.js',
                        'tests/casperjs/util/include/gh.api.tenant.js',
                        'tests/casperjs/util/include/gh.api.user.js',
                        'tests/casperjs/util/include/util.js'
                    ],
                    // Prepare te testing environment before starting the tests
                    'pre': ['tests/casperjs/util/prep.js'],
                    // Don't stop casperjs after first test failure
                    'failFast': false
                }
            }
        },
        'csslint': {
            'options': {
                'ids': false // ignore "Don't use IDs in CSS selectors" warning
            },
            'files': [
                'apps/**/*.css',
                'shared/gh/**/*.css'
            ]
        },
        'jshint': {
            'options': {
                'sub': true
            },
            'files': [
                'grunt.js',
                'apps/**/*.js',
                'shared/gh/**/*.js',
            ]
        },
        'qunit': {
            'gh': {
                'urls': ['http://admin.grasshopper.com/tests/qunit/tests/api.html'],
                'options': {
                    'urls': ['http://admin.grasshopper.com/tests/qunit/tests/api.html'],
                    'coverage': {
                        'disposeCollector': true,
                        'baseUrl': ".",
                        'src': ['shared/gh/api/*.js'],
                        'instrumentedFiles': 'target/coverage',
                        'lcovReport': 'coverage',
                        'linesThresholdPct': 85
                    }
                }
            }
        }
    });

    ///////////////
    // NPM TASKS //
    ///////////////

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-csslint');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-coveralls');
    grunt.loadNpmTasks('grunt-exec');
    grunt.loadNpmTasks('grunt-ghost');
    grunt.loadNpmTasks('grunt-qunit-istanbul');
    grunt.loadNpmTasks('grunt-text-replace');
    grunt.loadNpmTasks('grunt-ver');
    grunt.loadNpmTasks('grunt-qunit-istanbul');

    //////////////////
    // GRUNT TASKS  //
    //////////////////

    // Lint tasks for JavaScript and CSS
    grunt.registerTask('lint', ['jshint', 'csslint']);
    grunt.registerTask('test', ['lint', 'qunit', 'ghost']);

    /**
     * Task that changes the paths in the optimized Apache configuration files
     */
    grunt.registerTask('changePaths', function() {

        // Get all the apps
        var apps = fs.readdirSync('apps');
        var basedir = grunt.config('target') + '/optimized/';

        // Loop the Apache configuration files for every app
        _.each(apps, function(appName) {
            var file = basedir + 'apache/app_' + appName + '.conf';
            var fileContent = grunt.file.read(file);
            fileContent = fileContent.replace(/grasshopper-ui/g, 'grasshopper-ui/' + grunt.config('target') + '/optimized');
            grunt.file.write(file, fileContent);
            grunt.log.writeln(String('Apache file changed for app_' + appName + '.conf').green);
        });
    });

    /**
     * Task to fill out the Apache config template
     */
    grunt.registerTask('configApache', function() {
        var infile = './apache/apache.js';

        // Get all the apps
        var apps = fs.readdirSync('apps');

        // Get the config
        var apacheConfig = require('./apache/apache.js');

        // Get each apps config and overlay it
        _.each(apps, function(app) {
            apacheConfig[app] = require('./apps/' + app + '/apache/apache.js');
        });
        grunt.config.set('apacheConf', apacheConfig);

        // Render the httpd config
        var httpdTemplate = grunt.file.read('apache/httpd.conf');
        var renderedConfig = grunt.template.process(httpdTemplate);
        var outfile = grunt.config('target') + '/optimized/apache/httpd.conf';
        grunt.file.write(outfile, renderedConfig);
        grunt.log.writeln('httpd.conf rendered at '.green + outfile.green);

        // Render each app/vhost
        _.each(apps, function(appName) {
            apacheConfig[appName].errorLog = apacheConfig.logDirectory + appName + '_error.log';
            apacheConfig[appName].customLog = apacheConfig.logDirectory + appName + '_custom.log';

            var template = grunt.file.read('apps/' + appName + '/apache/app.conf');
            var renderedConfig = grunt.template.process(template);
            var outfile = grunt.config('target') + '/optimized/apache/app_' + appName + '.conf';
            grunt.file.write(outfile, renderedConfig);
            grunt.log.writeln(appName + '.conf rendered at '.green + outfile.green);
        });
    });

    /**
     * Task to hash files
     */
    grunt.registerTask('hashFiles', function() {
        this.requires('requirejs');

        // Hash the GH files
        grunt.task.run('ver:gh');

        // Update the files in the bootstrap
        grunt.task.run('updateBootstrapPaths');
    });

    /**
     * Task that creates a release build
     *
     * @param  {String}    outputDir    The directory where the build should be stored
     *
     *  * Example:
     *  * grunt release:/tmp/release
     *  *
     *  * This will run the entire UI build (minification, hashing, apache config, etc, ..) and create the following folders:
     *  * /tmp/release/optimized  -  contains the minified UI sources
     *  * /tmp/release/original   -  contains the original UI files
     *  *
     */
    grunt.registerTask('release', function(outputDir) {
        if (!outputDir) {
            return grunt.log.writeln('Please provide a path where the release files should be copied to'.red);
        }
        grunt.config.target = outputDir;

        // Run the default production build task
        grunt.task.run('default');

        // Change the paths in the optimized Apache files
        grunt.task.run('changePaths');
    });

    /**
     * Task to update the paths in gh.bootstrap to the hashed versions
     */
    grunt.registerTask('updateBootstrapPaths', function() {
        this.requires('ver:gh');

        var basedir = grunt.config('target') + '/optimized/';
        var hashedPaths = require('./' + grunt.config.get('ver.gh.version'));
        var bootstrapPath = basedir + hashedPaths['/shared/gh/api/gh.bootstrap.js'];
        var bootstrap = grunt.file.read(bootstrapPath);
        var regex = /("|')?paths("|')?: ?\{[^}]*\}/;
        var scriptPaths = 'paths = {' + bootstrap.match(regex)[0] + '}';

        var paths = vm.runInThisContext(scriptPaths).paths;

        // Update the bootstrap file with the hashed paths
        Object.keys(paths).forEach(function(key) {
            var prefix = '/shared/';
            var path = prefix + paths[key] + '.js';
            var hashedPath = '';
            if (hashedPaths[path]) {
                hashedPath = hashedPaths[path];
                // trim off prefix and .js
                paths[key] = hashedPath.substring(prefix.length, hashedPath.length - 3);
            }
        });
        bootstrap = bootstrap.replace(regex, 'paths:' + JSON.stringify(paths));
        grunt.file.write(bootstrapPath, bootstrap);
        grunt.log.writeln('Boots strapped'.green);
    });

    // Default task for production build
    grunt.registerTask('default', ['clean', 'copy', 'requirejs', 'hashFiles', 'exec:removeTarget', 'configApache']);
};

/**
 * Generate the glob expressions to match all extensions of files in the provided set of
 * directories. Any file with an extension that is found in the `excludeExts` option  will not be
 * hashed
 *
 * @param  {Object}     options                 An options object that specifies what files to hash
 * @param  {String[]}   options.directories     The list of directories whose files to hash
 * @param  {String[]}   [options.excludeExts]   The extensions of files to ignore when hashing files
 * @param  {String[]}   [options.extra]         Extra glob patterns to append, in addition to the ones added for the extensions
 * @return {String[]}                           An array of glob expressions that match the files to hash in the directories
 * @api private
 */
var _hashFiles = function(options) {
    options.excludeExts = options.excludeExts || [];
    options.extra = options.extra || [];

    var globs = [];
    _.each(options.directories, function(directory) {
        globs.push(util.format('%s/**', directory));
        _.each(options.excludeExts, function(ext) {
            // Exclude both direct children of the excluded extensions, and all grand-children
            globs.push(util.format('!%s/*.%s', directory, ext));
            globs.push(util.format('!%s/**/*.%s', directory, ext));
        });
    });

    return _.union(globs, options.extra);
};

/**
 * Generate the standard replacement references for the given resource directories, and also
 * include the provided "extra" replacement files.
 *
 * @param  {Object}     options                 An options object that specifies what files to hash
 * @param  {String[]}   options.directories     A list of directories whose resource paths should be replaced
 * @param  {String[]}   [options.includeExts]   The file extensions that should have replacement performed
 * @param  {String[]}   [options.extra]         Additional replacements to perform
 * @return {String[]}                           The full derived list of all resources that replacement should be performed
 * @api private
 */
var _replacementReferences = function(options) {
    options.includeExts = options.includeExts || [];
    options.extra = options.extra || [];

    var globs = [];
    _.each(options.directories, function(directory) {
        _.each(options.includeExts, function(ext) {
            globs.push(util.format('%s/**/*.%s', directory, ext));
        });
    });

    return _.union(globs, options.extra);
};
<commit_msg>Update references in the test files so tests work on production build<commit_after>/*!
 * Copyright 2014 Digital Services, University of Cambridge Licensed
 * under the Educational Community License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('lodash');
var fs = require('fs');
var util = require('util');
var vm = require('vm');

module.exports = function(grunt) {

    ///////////////////
    // CONFIGURATION //
    ///////////////////

    grunt.initConfig({
        'target': 'target',
        'clean': ['<%= target %>'],
        'exec': {
            'removeTarget': {
                'cmd': 'rm -rf <%= target %>/optimized/<%= target %>'
            }
        },
        'copy': {
            'main': {
                'files': [
                    {
                        'expand': true,
                        'src': [
                            '**',
                            '!<%= target %>/.*/**',
                            '!node_modules/**'
                        ],
                        'dest': '<%= target %>/original'
                    }
                ]
            }
        },
        'requirejs': {
            'optimize': {
                'options': {
                    'appDir': './',
                    'baseUrl': './shared',
                    'mainConfigFile': './shared/gh/api/gh.bootstrap.js',
                    'dir': '<%= target %>/optimized',
                    'optimize': 'uglify',
                    'preserveLicenseComments': false,
                    'optimizeCss': 'standard',
                    // TODO: Replace this with a saner value
                    // @see https://github.com/jrburke/r.js/pull/653
                    'cssImportIgnore': '//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,400,300,600,700&subset=latin,cyrillic-ext,latin-ext,greek-ext',
                    'inlineText': true,
                    'useStrict': false,
                    'pragmas': {},
                    'skipPragmas': false,
                    'skipModuleInsertion': false,
                    'modules': [{
                        'name': 'gh.core'
                    }],
                    'fileExclusionRegExp': /^(\.|apache|etc|node_modules|tools)/,
                    'logLevel': 2
                }
            }
        },
        'ver': {
            'gh': {
                'basedir': '<%= target %>/optimized',
                'phases': [

                    // 1. Hash all the vendor fonts
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/fonts'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/css',
                            ],
                            'includeExts': ['css']
                        })
                    },

                    // 2. Hash all the vendor CSS and JS
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/vendor/css',
                                '<%= target %>/optimized/shared/vendor/js'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/apps',
                                '<%= target %>/optimized/shared',
                                '<%= target %>/optimized/tests'
                            ],
                            'includeExts': ['html']
                        })
                    },

                    // 3. Hash the GH CSS and JS files
                    {
                        'files': _hashFiles({
                            'directories': [
                                '<%= target %>/optimized/shared/gh/**'
                            ]
                        }),
                        'references': _replacementReferences({
                            'directories': [
                                '<%= target %>/optimized/apps',
                                '<%= target %>/optimized/shared',
                                '<%= target %>/optimized/tests'
                            ],
                            'includeExts': ['html']
                        })
                    }
                ],
                'version': '<%= target %>/optimized/hashes.json'
            }
        },
        'coveralls': {
            'gh': {
                'src': 'coverage/lcov.info',
                'options': {
                    'src': 'coverage/lcov.info'
                }
            }
        },
        'ghost': {
            'dist': {
                'filesSrc': [
                    'tests/casperjs/tests/*.js'
                ],
                // CasperJS test command options
                'options': {
                    // Specify the files to be included in each test
                    'includes': [
                        'tests/casperjs/util/include/gh.api.admin.js',
                        'tests/casperjs/util/include/gh.api.app.js',
                        'tests/casperjs/util/include/gh.api.authentication.js',
                        'tests/casperjs/util/include/gh.api.config.js',
                        'tests/casperjs/util/include/gh.api.event.js',
                        'tests/casperjs/util/include/gh.api.orgunit.js',
                        'tests/casperjs/util/include/gh.api.series.js',
                        'tests/casperjs/util/include/gh.api.tenant.js',
                        'tests/casperjs/util/include/gh.api.user.js',
                        'tests/casperjs/util/include/util.js'
                    ],
                    // Prepare te testing environment before starting the tests
                    'pre': ['tests/casperjs/util/prep.js'],
                    // Don't stop casperjs after first test failure
                    'failFast': false
                }
            }
        },
        'csslint': {
            'options': {
                'ids': false // ignore "Don't use IDs in CSS selectors" warning
            },
            'files': [
                'apps/**/*.css',
                'shared/gh/**/*.css'
            ]
        },
        'jshint': {
            'options': {
                'sub': true
            },
            'files': [
                'grunt.js',
                'apps/**/*.js',
                'shared/gh/**/*.js',
            ]
        },
        'qunit': {
            'gh': {
                'urls': ['http://admin.grasshopper.com/tests/qunit/tests/api.html'],
                'options': {
                    'urls': ['http://admin.grasshopper.com/tests/qunit/tests/api.html'],
                    'coverage': {
                        'disposeCollector': true,
                        'baseUrl': ".",
                        'src': ['shared/gh/api/*.js'],
                        'instrumentedFiles': 'target/coverage',
                        'lcovReport': 'coverage',
                        'linesThresholdPct': 85
                    }
                }
            }
        }
    });

    ///////////////
    // NPM TASKS //
    ///////////////

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-csslint');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-coveralls');
    grunt.loadNpmTasks('grunt-exec');
    grunt.loadNpmTasks('grunt-ghost');
    grunt.loadNpmTasks('grunt-qunit-istanbul');
    grunt.loadNpmTasks('grunt-text-replace');
    grunt.loadNpmTasks('grunt-ver');
    grunt.loadNpmTasks('grunt-qunit-istanbul');

    //////////////////
    // GRUNT TASKS  //
    //////////////////

    // Lint tasks for JavaScript and CSS
    grunt.registerTask('lint', ['jshint', 'csslint']);
    grunt.registerTask('test', ['lint', 'qunit', 'ghost']);

    /**
     * Task that changes the paths in the optimized Apache configuration files
     */
    grunt.registerTask('changePaths', function() {

        // Get all the apps
        var apps = fs.readdirSync('apps');
        var basedir = grunt.config('target') + '/optimized/';

        // Loop the Apache configuration files for every app
        _.each(apps, function(appName) {
            var file = basedir + 'apache/app_' + appName + '.conf';
            var fileContent = grunt.file.read(file);
            fileContent = fileContent.replace(/grasshopper-ui/g, 'grasshopper-ui/' + grunt.config('target') + '/optimized');
            grunt.file.write(file, fileContent);
            grunt.log.writeln(String('Apache file changed for app_' + appName + '.conf').green);
        });
    });

    /**
     * Task to fill out the Apache config template
     */
    grunt.registerTask('configApache', function() {
        var infile = './apache/apache.js';

        // Get all the apps
        var apps = fs.readdirSync('apps');

        // Get the config
        var apacheConfig = require('./apache/apache.js');

        // Get each apps config and overlay it
        _.each(apps, function(app) {
            apacheConfig[app] = require('./apps/' + app + '/apache/apache.js');
        });
        grunt.config.set('apacheConf', apacheConfig);

        // Render the httpd config
        var httpdTemplate = grunt.file.read('apache/httpd.conf');
        var renderedConfig = grunt.template.process(httpdTemplate);
        var outfile = grunt.config('target') + '/optimized/apache/httpd.conf';
        grunt.file.write(outfile, renderedConfig);
        grunt.log.writeln('httpd.conf rendered at '.green + outfile.green);

        // Render each app/vhost
        _.each(apps, function(appName) {
            apacheConfig[appName].errorLog = apacheConfig.logDirectory + appName + '_error.log';
            apacheConfig[appName].customLog = apacheConfig.logDirectory + appName + '_custom.log';

            var template = grunt.file.read('apps/' + appName + '/apache/app.conf');
            var renderedConfig = grunt.template.process(template);
            var outfile = grunt.config('target') + '/optimized/apache/app_' + appName + '.conf';
            grunt.file.write(outfile, renderedConfig);
            grunt.log.writeln(appName + '.conf rendered at '.green + outfile.green);
        });
    });

    /**
     * Task to hash files
     */
    grunt.registerTask('hashFiles', function() {
        this.requires('requirejs');

        // Hash the GH files
        grunt.task.run('ver:gh');

        // Update the files in the bootstrap
        grunt.task.run('updateBootstrapPaths');
    });

    /**
     * Task that creates a release build
     *
     * @param  {String}    outputDir    The directory where the build should be stored
     *
     *  * Example:
     *  * grunt release:/tmp/release
     *  *
     *  * This will run the entire UI build (minification, hashing, apache config, etc, ..) and create the following folders:
     *  * /tmp/release/optimized  -  contains the minified UI sources
     *  * /tmp/release/original   -  contains the original UI files
     *  *
     */
    grunt.registerTask('release', function(outputDir) {
        if (!outputDir) {
            return grunt.log.writeln('Please provide a path where the release files should be copied to'.red);
        }
        grunt.config.target = outputDir;

        // Run the default production build task
        grunt.task.run('default');

        // Change the paths in the optimized Apache files
        grunt.task.run('changePaths');
    });

    /**
     * Task to update the paths in gh.bootstrap to the hashed versions
     */
    grunt.registerTask('updateBootstrapPaths', function() {
        this.requires('ver:gh');

        var basedir = grunt.config('target') + '/optimized/';
        var hashedPaths = require('./' + grunt.config.get('ver.gh.version'));
        var bootstrapPath = basedir + hashedPaths['/shared/gh/api/gh.bootstrap.js'];
        var bootstrap = grunt.file.read(bootstrapPath);
        var regex = /("|')?paths("|')?: ?\{[^}]*\}/;
        var scriptPaths = 'paths = {' + bootstrap.match(regex)[0] + '}';

        var paths = vm.runInThisContext(scriptPaths).paths;

        // Update the bootstrap file with the hashed paths
        Object.keys(paths).forEach(function(key) {
            var prefix = '/shared/';
            var path = prefix + paths[key] + '.js';
            var hashedPath = '';
            if (hashedPaths[path]) {
                hashedPath = hashedPaths[path];
                // trim off prefix and .js
                paths[key] = hashedPath.substring(prefix.length, hashedPath.length - 3);
            }
        });
        bootstrap = bootstrap.replace(regex, 'paths:' + JSON.stringify(paths));
        grunt.file.write(bootstrapPath, bootstrap);
        grunt.log.writeln('Boots strapped'.green);
    });

    // Default task for production build
    grunt.registerTask('default', ['clean', 'copy', 'requirejs', 'hashFiles', 'exec:removeTarget', 'configApache']);
};

/**
 * Generate the glob expressions to match all extensions of files in the provided set of
 * directories. Any file with an extension that is found in the `excludeExts` option  will not be
 * hashed
 *
 * @param  {Object}     options                 An options object that specifies what files to hash
 * @param  {String[]}   options.directories     The list of directories whose files to hash
 * @param  {String[]}   [options.excludeExts]   The extensions of files to ignore when hashing files
 * @param  {String[]}   [options.extra]         Extra glob patterns to append, in addition to the ones added for the extensions
 * @return {String[]}                           An array of glob expressions that match the files to hash in the directories
 * @api private
 */
var _hashFiles = function(options) {
    options.excludeExts = options.excludeExts || [];
    options.extra = options.extra || [];

    var globs = [];
    _.each(options.directories, function(directory) {
        globs.push(util.format('%s/**', directory));
        _.each(options.excludeExts, function(ext) {
            // Exclude both direct children of the excluded extensions, and all grand-children
            globs.push(util.format('!%s/*.%s', directory, ext));
            globs.push(util.format('!%s/**/*.%s', directory, ext));
        });
    });

    return _.union(globs, options.extra);
};

/**
 * Generate the standard replacement references for the given resource directories, and also
 * include the provided "extra" replacement files.
 *
 * @param  {Object}     options                 An options object that specifies what files to hash
 * @param  {String[]}   options.directories     A list of directories whose resource paths should be replaced
 * @param  {String[]}   [options.includeExts]   The file extensions that should have replacement performed
 * @param  {String[]}   [options.extra]         Additional replacements to perform
 * @return {String[]}                           The full derived list of all resources that replacement should be performed
 * @api private
 */
var _replacementReferences = function(options) {
    options.includeExts = options.includeExts || [];
    options.extra = options.extra || [];

    var globs = [];
    _.each(options.directories, function(directory) {
        _.each(options.includeExts, function(ext) {
            globs.push(util.format('%s/**/*.%s', directory, ext));
        });
    });

    return _.union(globs, options.extra);
};
<|endoftext|>


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

  // Show elapsed time after tasks run
  require('time-grunt')(grunt);
  // Load all Grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    kollab: {
      app: 'app',
      dev: '_dev',
      dist: '_dist'
    },
    clean: {
      grunticon: {
        src: ['<%= kollab.app %>/svgs/grunticon', '<% kollab.app %>/svgs/images']
      },
      server: [
        '_dev'
      ],
      dist: [
        '_dist'
      ]
    },
    grunticon: {
      icons: {
        options: {
          src: '<%= kollab.app %>/svgs/',
          dest: '<%= kollab.app %>/svgs/grunticon',
          pngfolder: '<%= kollab.app %>/images/',
          datasvgcss: '_icons.data.svg.scss',
          datapngcss: '_icons.data.png.scss',
          urlpngcss: '_icons.fallback.scss'
        }
      }
    },
    compass: {
      options: {
        sassDir: '<%= kollab.app %>/_scss',
        imagesDir: '<%= kollab.app %>/img',
        generatedImagesDir: '<%= kollab.app %>/img',
        javascriptsDir: '<%= kollab.app %>/js',
        fontsDir: '<%= kollab.app %>/fonts',
        assetCacheBuster: 'none',
        require: [
          'sass-globbing',
          'toolkit',
          'rgbapng'
        ]
      },
      server: {
        options: {
          cssDir: '<%= kollab.dev %>/css',
          environment: 'development',
          outputStyle: 'expanded',
          relativeAssets: true,
          raw: 'line_numbers = :true\n'
        }
      },
      dist: {
        options: {
          cssDir: '<%= kollab.dist %>/css',
          environment: 'production',
          outputStyle: 'compressed',
          force: true
        }
      }
    },
    watch: {
      compass: {
        files: ['<%= kollab.app %>/_scss/**/*.scss'],
        tasks: ['compass:server']
      },
      jekyll: {
        files: [
          '<%= kollab.app %>/**/*.{html,yml,md,mkd,markdown}'
        ],
        tasks: ['jekyll:server', 'copy:server']
      },
      js: {
        files: ['<%= kollab.app %>/js/*.js','<%= kollab.app %>/js/vendor/*.js'],
        tasks: ['concat:server', 'uglify:server']
      },
      copy: {
        files: [
          '<%= kollab.app %>css/*}',
          '<%= kollab.app %>img/*}',
          '<%= kollab.app %>js/*}'
        ],
        tasks: ['copy:server']
      }
    },
    jekyll: {
      options: {
        // bundleExec: true,
        config: '_config.yml',
        src: '<%= kollab.app %>'
      },
      dist: {
        options: {
          dest: '<%= kollab.dist %>',
        }
      },
      server: {
        options: {
          config: '_config.yml',
          dest: '_dev'
        }
      }
    },
    copy: {
      grunticon: {
        files: [
          {expand: true, flatten: true, src: ['svgs/images/**'], dest: '../images/', filter: 'isFile'},
          {expand: true, flatten: true, src: ['svgs/grunticon/*.scss'], dest: 'scss/partials/utility/'},
        ]
      },
      server: {
        files: [
          { expand: true, cwd: '<%= kollab.app %>/css', src: '**/*.css', dest: '<%= kollab.dev %>/css' },
          { expand: true, cwd: '<%= kollab.app %>/img', src: '**', dest: '<%= kollab.dev %>/img' },
          { expand: true, cwd: '<%= kollab.app %>/js', src: '**/*.js', dest: '<%= kollab.dev %>/js' }
        ]
      },
      dist: {
        files: [
          {expand: true, src: ['../images/**'], dest: '_dist/images'},
          {expand: true, src: ['js/no-concat/modernizr.js'], dest: '_dist/'},
        ]
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      server: {
        src: ['<%= kollab.app %>/js/vendor/*.js','<%= kollab.app %>/js/*.js'],
        dest: '<%= kollab.dev %>/js/compiled.js'
      },
      dist: {
        src: ['js/vendor/*.js','js/*.js'],
        dest: '_dist/js/compiled.js'
      }
    },
    uglify: {
      server: {
        files: {
          '<%= kollab.dev %>/js/compiled.min.js': '<%= kollab.dev %>/js/compiled.js'
        }
      },
      dist: {
        files: {
          '_dist/js/compiled.min.js': '_dist/js/compiled.js'
        }
      }
    },
    concurrent: {
      server: [
        'compass:server',
        'jekyll:server'
      ],
      dist: [
        'compass:dist',
        'copy:dist'
      ]
    }
  });

  // Create svg stylesheets and fallback from svgs
  grunt.registerTask('images', ['grunticon', 'copy:grunticon', 'clean:grunticon']);

  // Development build on all assets
  grunt.registerTask(
    'serve',
    'Serves the Jekyll Site for development',
    ['clean:server', 'jekyll:server', 'compass:server', 'copy:server', 'watch' ]
  );

  // Development build on all assets
  grunt.registerTask(
    'dev',
    'Compiles all of the assets moves them to correct places for the theme to run on development',
    ['images', 'compass:dev', 'concat:dev', 'uglify:dev']
  );

  // Distribution build on all assets. These then will need to be
  // manually moved to correct directories from "_dist" directory
  grunt.registerTask(
    'dist',
    'Compiles all of the assets and copies the files to the distribution directory.',
    ['clean:dist', 'jekyll:dist', 'compass:dist', 'concat:dist', 'uglify:dist', 'copy:dist']
  );
};
<commit_msg>updated grunt config<commit_after>module.exports = function(grunt) {

  // Show elapsed time after tasks run
  require('time-grunt')(grunt);
  // Load all Grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    kollab: {
      app: 'app',
      dev: '_dev',
      dist: '_dist'
    },
    clean: {
      grunticon: {
        src: ['<%= kollab.app %>/svgs/grunticon', '<% kollab.app %>/svgs/images']
      },
      server: [
        '_dev'
      ],
      dist: [
        '_dist'
      ]
    },
    grunticon: {
      icons: {
        options: {
          src: '<%= kollab.app %>/svgs/',
          dest: '<%= kollab.app %>/svgs/grunticon',
          pngfolder: '<%= kollab.app %>/images/',
          datasvgcss: '_icons.data.svg.scss',
          datapngcss: '_icons.data.png.scss',
          urlpngcss: '_icons.fallback.scss'
        }
      }
    },
    compass: {
      options: {
        sassDir: '<%= kollab.app %>/_scss',
        imagesDir: '<%= kollab.app %>/img',
        generatedImagesDir: '<%= kollab.app %>/img',
        javascriptsDir: '<%= kollab.app %>/js',
        fontsDir: '<%= kollab.app %>/fonts',
        assetCacheBuster: 'none',
        require: [
          'sass-globbing',
          'toolkit',
          'rgbapng'
        ]
      },
      server: {
        options: {
          cssDir: '<%= kollab.dev %>/css',
          environment: 'development',
          outputStyle: 'expanded',
          relativeAssets: true,
          raw: 'line_numbers = :true\n'
        }
      },
      dist: {
        options: {
          cssDir: '<%= kollab.dist %>/css',
          environment: 'production',
          outputStyle: 'compressed',
          force: true
        }
      }
    },
    watch: {
      compass: {
        files: ['<%= kollab.app %>/_scss/**/*.scss'],
        tasks: ['compass:server']
      },
      jekyll: {
        files: [
          '<%= kollab.app %>/**/*.{html,yml,md,mkd,markdown}'
        ],
        tasks: ['jekyll:server', 'copy:server']
      },
      js: {
        files: ['<%= kollab.app %>/js/*.js','<%= kollab.app %>/js/vendor/*.js'],
        tasks: ['concat:server', 'uglify:server']
      },
      copy: {
        files: [
          '<%= kollab.app %>css/*}',
          '<%= kollab.app %>img/*}',
          '<%= kollab.app %>js/*}'
        ],
        tasks: ['copy:server']
      }
    },
    jekyll: {
      options: {
        // bundleExec: true,
        config: '_config.yml',
        src: '<%= kollab.app %>'
      },
      dist: {
        options: {
          dest: '<%= kollab.dist %>',
        }
      },
      server: {
        options: {
          config: '_config.yml',
          dest: '_dev'
        }
      }
    },
    copy: {
      grunticon: {
        files: [
          {expand: true, flatten: true, src: ['svgs/images/**'], dest: '../images/', filter: 'isFile'},
          {expand: true, flatten: true, src: ['svgs/grunticon/*.scss'], dest: 'scss/partials/utility/'},
        ]
      },
      server: {
        files: [
          { expand: true, cwd: '<%= kollab.app %>/css', src: '**/*.css', dest: '<%= kollab.dev %>/css' },
          { expand: true, cwd: '<%= kollab.app %>/img', src: '**', dest: '<%= kollab.dev %>/img' },
          { expand: true, cwd: '<%= kollab.app %>/js', src: '**/*.js', dest: '<%= kollab.dev %>/js' }
        ]
      },
      dist: {
        files: [
          {expand: true, src: ['../images/**'], dest: '_dist/images'},
          {expand: true, src: ['js/no-concat/modernizr.js'], dest: '_dist/'},
        ]
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      server: {
        src: ['<%= kollab.app %>/js/vendor/*.js','<%= kollab.app %>/js/*.js'],
        dest: '<%= kollab.dev %>/js/compiled.js'
      },
      dist: {
        src: ['<%= kollab.app %>/js/vendor/*.js','<%= kollab.app %>/js/*.js'],
        dest: '_dist/js/compiled.js'
      }
    },
    uglify: {
      server: {
        files: {
          '<%= kollab.dev %>/js/compiled.min.js': '<%= kollab.dev %>/js/compiled.js'
        }
      },
      dist: {
        files: {
          '_dist/js/compiled.min.js': '_dist/js/compiled.js'
        }
      }
    },
    concurrent: {
      server: [
        'compass:server',
        'jekyll:server'
      ],
      dist: [
        'compass:dist',
        'copy:dist'
      ]
    }
  });

  // Create svg stylesheets and fallback from svgs
  grunt.registerTask('images', ['grunticon', 'copy:grunticon', 'clean:grunticon']);

  // Development build on all assets
  grunt.registerTask(
    'serve',
    'Serves the Jekyll Site for development',
    ['clean:server', 'jekyll:server', 'compass:server', 'copy:server', 'watch' ]
  );

  // Development build on all assets
  grunt.registerTask(
    'dev',
    'Compiles all of the assets moves them to correct places for the theme to run on development',
    ['images', 'compass:dev', 'concat:dev', 'uglify:dev']
  );

  // Distribution build on all assets. These then will need to be
  // manually moved to correct directories from "_dist" directory
  grunt.registerTask(
    'dist',
    'Compiles all of the assets and copies the files to the distribution directory.',
    ['clean:dist', 'jekyll:dist', 'compass:dist', 'concat:dist', 'uglify:dist', 'copy:dist']
  );
};
<|endoftext|>


<commit_before>/*jslint nomen: true */
/*globals define: true */

define([
  'jquery',
  'lib/lodash',
  'backbone',
  'lib/tinypubsub',

  // LocalData
  'settings',
  'api',

  // Models
  'models/responses',

  // Views
  'views/responses/item',

  // Templates
  'text!templates/responses/list.html'
],

function($, _, Backbone, events, settings, api, Responses, ResponseView, template) {
  'use strict';

  /**
   * Intended for shorter lists of responses (arbitrarily <25)
   * Doesn't include pagination, which isn't relevant in this case.
   * See responses/responses/ListView for a heavyweight implementation.
   */
  var ResponseListView = Backbone.View.extend({
    className: 'responses',

    template: _.template(template),

    events: {
      'click .close': 'remove'
    },

    initialize: function() {
      this.listenTo(this.collection, 'add', this.render);
      this.listenTo(this.collection, 'reset', this.render);
    },

    remove: function() {
      this.$el.empty();
      this.stopListening();
      this.trigger('delete');
      return this;
    },

    render: function() {
      var first = this.collection.at(0);
      var name;

      if(first.get('geo_info') != undefined) {
        name = first.get('geo_info').humanReadableName;
      }else {
        name = first.get('parcel_id');
      }

      var $el = $(this.el);
      $el.html(this.template({ name: name }));

      this.collection.each(function(response) {
        var item = new ResponseView({ model: response });
        $el.find('.responses-list').append(item.render().el);
      });

      return this;
    }
  });

  return ResponseListView;

});
<commit_msg>Typo fix in response list<commit_after>/*jslint nomen: true */
/*globals define: true */

define([
  'jquery',
  'lib/lodash',
  'backbone',
  'lib/tinypubsub',

  // LocalData
  'settings',
  'api',

  // Models
  'models/responses',

  // Views
  'views/responses/item',

  // Templates
  'text!templates/responses/list.html'
],

function($, _, Backbone, events, settings, api, Responses, ResponseView, template) {
  'use strict';

  /**
   * Intended for shorter lists of responses (arbitrarily <25)
   * Doesn't include pagination, which isn't relevant in this case.
   * See responses/responses/ListView for a heavyweight implementation.
   */
  var ResponseListView = Backbone.View.extend({
    className: 'responses',

    template: _.template(template),

    events: {
      'click .close': 'remove'
    },

    initialize: function() {
      this.listenTo(this.collection, 'add', this.render);
      this.listenTo(this.collection, 'reset', this.render);
    },

    remove: function() {
      this.$el.empty();
      this.stopListening();
      this.trigger('delete');
      return this;
    },

    render: function() {
      var first = this.collection.at(0);
      var name;

      if(first.get('geo_info') !== undefined) {
        name = first.get('geo_info').humanReadableName;
      }else {
        name = first.get('parcel_id');
      }

      var $el = $(this.el);
      $el.html(this.template({ name: name }));

      this.collection.each(function(response) {
        var item = new ResponseView({ model: response });
        $el.find('.responses-list').append(item.render().el);
      });

      return this;
    }
  });

  return ResponseListView;

});
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {

    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        cssmin: {
            options: {
                shorthandCompacting: false,
                roundingPrecision: -1,
                sourceMap: true
            },
            shuwee: {
                files: {
                    'src/Resources/public/css/shuwee_admin.min.css': [
                        'src/Resources/public/css/shuwee_admin/base.css'
                    ]
                }
            },
            vendors: {
                files: {
                    'src/Resources/public/css/vendors.min.css': [
                        'src/Resources/public/css/vendors/bootstrap.min.css',
                        'src/Resources/public/css/vendors/bootstrap-markdown.min.css'
                    ]
                }
            }
        },
        jshint: {
            shuwee: [
                'src/Resources/public/js/shuwee_admin/*.js'
            ]
        },
        sass: {
            dist: {
                options: {
                    style: 'expanded',
                    debugInfo: false,
                    lineNumbers: false
                },
                files: [{
                    expand: true,
                    debugInfo: false,
                    lineNumbers: false,
                    cwd: 'src/Resources/public/scss/',
                    src: ['*.scss'],
                    dest: 'src/Resources/public/css/shuwee_admin/',
                    ext: '.css'
                }]
            }
        },
        uglify: {
            options: {
                mangle: false,
                sourceMap: true
            },
            // Uglify both Shuwee and vendors are all vendors are not minified by default (and so it generates a map for us
            shuwee: {
                files: {
                    'src/Resources/public/js/shuwee_admin.min.js': [
                        // do not use *.js as order is important
                        'src/Resources/public/js/shuwee_admin/common.js',
                        'src/Resources/public/js/shuwee_admin/forms.js'
                    ]
                }
            },
            vendors: {
                files: {
                    'src/Resources/public/js/vendors.min.js': [
                        // do not use *.js as order is important
                        'src/Resources/public/js/vendors/jquery.min.js',
                        'src/Resources/public/js/vendors/bootstrap.min.js',
                        'src/Resources/public/js/vendors/markdown.js',
                        'src/Resources/public/js/vendors/bootstrap-markdown.js',
                        'src/Resources/public/js/vendors/stacktable.js'
                    ]
                }
            }
        },
        watch: {
            options: {
                livereload: true
            },
            css: {
                files: 'src/Resources/public/scss/**',
                tasks: ['sass', 'cssmin:shuwee'],
                options: {
                    interrupt: true
                }
            },
            js: {
                files: 'src/Resources/public/js/shuwee_admin/**',
                tasks: ['jshint', 'uglify:shuwee'],
                options: {
                    interrupt: true
                }
            }
        }
    });

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

    /**
     * Build and watch easy to debug resources for development.
     */
    grunt.registerTask('dev', [
        'sass',
        'jshint',
        'watch'
    ]);

    /**
     * Build minified resources for production
     */
    grunt.registerTask('dist', [
        'sass',
        'uglify',
        'cssmin'
    ]);
};
<commit_msg>Disable advanced CSS optimisations like selector merging.<commit_after>'use strict';

module.exports = function (grunt) {

    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        cssmin: {
            options: {
                shorthandCompacting: false,
                roundingPrecision: -1,
                sourceMap: true,
                advanced: false
            },
            shuwee: {
                files: {
                    'src/Resources/public/css/shuwee_admin.min.css': [
                        'src/Resources/public/css/shuwee_admin/base.css'
                    ]
                }
            },
            vendors: {
                files: {
                    'src/Resources/public/css/vendors.min.css': [
                        'src/Resources/public/css/vendors/bootstrap.min.css',
                        'src/Resources/public/css/vendors/bootstrap-markdown.min.css'
                    ]
                }
            }
        },
        jshint: {
            shuwee: [
                'src/Resources/public/js/shuwee_admin/*.js'
            ]
        },
        sass: {
            dist: {
                options: {
                    style: 'expanded',
                    debugInfo: false,
                    lineNumbers: false
                },
                files: [{
                    expand: true,
                    debugInfo: false,
                    lineNumbers: false,
                    cwd: 'src/Resources/public/scss/',
                    src: ['*.scss'],
                    dest: 'src/Resources/public/css/shuwee_admin/',
                    ext: '.css'
                }]
            }
        },
        uglify: {
            options: {
                mangle: false,
                sourceMap: true
            },
            // Uglify both Shuwee and vendors are all vendors are not minified by default (and so it generates a map for us
            shuwee: {
                files: {
                    'src/Resources/public/js/shuwee_admin.min.js': [
                        // do not use *.js as order is important
                        'src/Resources/public/js/shuwee_admin/common.js',
                        'src/Resources/public/js/shuwee_admin/forms.js'
                    ]
                }
            },
            vendors: {
                files: {
                    'src/Resources/public/js/vendors.min.js': [
                        // do not use *.js as order is important
                        'src/Resources/public/js/vendors/jquery.min.js',
                        'src/Resources/public/js/vendors/bootstrap.min.js',
                        'src/Resources/public/js/vendors/markdown.js',
                        'src/Resources/public/js/vendors/bootstrap-markdown.js',
                        'src/Resources/public/js/vendors/stacktable.js'
                    ]
                }
            }
        },
        watch: {
            options: {
                livereload: true
            },
            css: {
                files: 'src/Resources/public/scss/**',
                tasks: ['sass', 'cssmin:shuwee'],
                options: {
                    interrupt: true
                }
            },
            js: {
                files: 'src/Resources/public/js/shuwee_admin/**',
                tasks: ['jshint', 'uglify:shuwee'],
                options: {
                    interrupt: true
                }
            }
        }
    });

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

    /**
     * Build and watch easy to debug resources for development.
     */
    grunt.registerTask('dev', [
        'sass',
        'jshint',
        'watch'
    ]);

    /**
     * Build minified resources for production
     */
    grunt.registerTask('dist', [
        'sass',
        'uglify',
        'cssmin'
    ]);
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		concat: {
			options: {
			    separator: '\n\n'
			},
			youtyping: {
				src: ['src/control.js', 'src/util.js'],
				dest: 'youtyping.js',
				options: {
					banner: '/* youtyping.js <%= grunt.template.today("mm-dd-yyyy") %> */\n\n(function(exports){\n',
					footer: '\n\nexports.YouTyping = YouTyping;\n}(typeof window === \'undefined\' ? module.exports : window));'
				}
			},
			screen: {
				src: ['src/screen.js', 'src/util.js'],
				dest: 'youtyping-screen.js',
				options: {
					banner: '/* youtyping-screen.js <%= grunt.template.today("mm-dd-yyyy") %> */\n\n(function(exports){\n',
					footer: '\n\nexports.Screen = Screen;\n}(typeof window === \'undefined\' ? module.exports : window));'
				}
			}
		},
		uglify: {
			youtyping: {
				options: {
					banner: '/* youtyping.js <%= grunt.template.today("mm-dd-yyyy") %> */\n'
				},
				files: {
					'youtyping.min.js': ['<%= concat.youtyping.dest %>']
				},
				options: {
					sourceMap: true
				}
			},
			screen: {
				options: {
					banner: '/* youtyping-screen.js <%= grunt.template.today("mm-dd-yyyy") %> */\n'
				},
				files: {
					'youtyping-screen.min.js': ['<%= concat.screen.dest %>']
				},
				options: {
					sourceMap: true
				}
			}
		},
		jshint: {
			options: {
				camelcase: true,
				curly: true, // no more GOTO FAIL ;)
				eqeqeq: true,
				es3: true,
				forin: true,
				newcap: true,
				nonbsp: true,
				quotmark: true,
				multistr: true,
				laxbreak: true
			},
			src: {
				src: ['src/*.js']
			},
			youtyping: {
				src: ['youtyping.js'],
				options: {
					undef: true,
					browser: true,
					node: true,
					jquery: true,
					devel: true,
					globals: {
						// YouTube Iframe Player API
						YT: false,
						// paper.js
						paper: false
					}
				}
			},
			screen: {
				src: ['youtyping-screen.js'],
				options: {
					undef: true,
					browser: true,
					node: true,
					jquery: true,
					devel: true,
					globals: {
						// YouTube Iframe Player API
						YT: false,
						// paper.js
						paper: false,
						// YouTyping interfaces
						YouTyping: true
					}
				}
			}
		},
		connect: {
			server: {
				options: {
					port: 8080,
					debug: true,
					keepalive: true,
					open: 'http://localhost:8080/sample/'
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('default', ['concat', 'jshint', 'uglify']);
	grunt.registerTask('debug', ['concat', 'jshint', 'uglify', 'connect']);
};
<commit_msg>Change grunt order<commit_after>module.exports = function (grunt) {
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		concat: {
			options: {
			    separator: '\n\n'
			},
			youtyping: {
				src: ['src/control.js', 'src/util.js'],
				dest: 'youtyping.js',
				options: {
					banner: '/* youtyping.js <%= grunt.template.today("mm-dd-yyyy") %> */\n\n(function(exports){\n',
					footer: '\n\nexports.YouTyping = YouTyping;\n}(typeof window === \'undefined\' ? module.exports : window));'
				}
			},
			screen: {
				src: ['src/screen.js', 'src/util.js'],
				dest: 'youtyping-screen.js',
				options: {
					banner: '/* youtyping-screen.js <%= grunt.template.today("mm-dd-yyyy") %> */\n\n(function(exports){\n',
					footer: '\n\nexports.Screen = Screen;\n}(typeof window === \'undefined\' ? module.exports : window));'
				}
			}
		},
		uglify: {
			youtyping: {
				options: {
					banner: '/* youtyping.js <%= grunt.template.today("mm-dd-yyyy") %> */\n'
				},
				files: {
					'youtyping.min.js': ['<%= concat.youtyping.dest %>']
				},
				options: {
					sourceMap: true
				}
			},
			screen: {
				options: {
					banner: '/* youtyping-screen.js <%= grunt.template.today("mm-dd-yyyy") %> */\n'
				},
				files: {
					'youtyping-screen.min.js': ['<%= concat.screen.dest %>']
				},
				options: {
					sourceMap: true
				}
			}
		},
		jshint: {
			options: {
				camelcase: true,
				curly: true, // no more GOTO FAIL ;)
				eqeqeq: true,
				es3: true,
				forin: true,
				newcap: true,
				nonbsp: true,
				quotmark: true,
				multistr: true,
				laxbreak: true
			},
			src: {
				src: ['src/*.js']
			},
			youtyping: {
				src: ['youtyping.js'],
				options: {
					undef: true,
					browser: true,
					node: true,
					jquery: true,
					devel: true,
					globals: {
						// YouTube Iframe Player API
						YT: false,
						// paper.js
						paper: false
					}
				}
			},
			screen: {
				src: ['youtyping-screen.js'],
				options: {
					undef: true,
					browser: true,
					node: true,
					jquery: true,
					devel: true,
					globals: {
						// YouTube Iframe Player API
						YT: false,
						// paper.js
						paper: false,
						// YouTyping interfaces
						YouTyping: true
					}
				}
			}
		},
		connect: {
			server: {
				options: {
					port: 8080,
					debug: true,
					keepalive: true,
					open: 'http://localhost:8080/sample/'
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('default', [
		'jshint:src',
		'concat',
		'jshint:youtyping',
		'jshint:screen',
		'uglify'
	]);
	grunt.registerTask('debug', ['concat', 'jshint', 'uglify', 'connect']);
};
<|endoftext|>


<commit_before>/*global require, module:false */
module.exports = function(grunt) {
    var distJs = 'dist/js/',
        distCss = 'dist/css/';

    // Project configuration.
    grunt.initConfig({
        // Metadata.
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',

        // Task configuration.
        concat: {
            options: {
                banner: '<%= banner %>',
                stripBanners: true
            },
            js: {
                src: ['src/js/*.js'],
                dest: distJs + '<%= pkg.name %>.js'
            },
            css: {
                src: ['src/css/*.css'],
                dest: distCss + '<%= pkg.name %>.css'
            }
        },

        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            dist: {
                src: '<%= concat.js.dest %>',
                dest: distJs + '<%= pkg.name %>.min.js'
            }
        },

        cssmin: {
            minify: {
                src: 'dist/css/glb.share.css',
                dest: 'dist/css/glb.share.min.css',
                banner: '<%= banner %>'
            }
        },

        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                unused: true,
                boss: true,
                eqnull: true,
                browser: true,
                globals: {}
            },
            gruntfile: {
                src: 'Gruntfile.js'
            },
            test: {
                src: ['<%= concat.js.src %>', 'tests/*.spec.js']
            }
        },

        compass: {
            dist: {
                options: {
                    sassDir: 'src/sass',
                    cssDir: 'src/css',
                    outputStyle: 'compressed',
                    noLineComments: true,
                    relativeAssets: true

                }
            }
        },

        svgstore: {
            options: {
                prefix : 'icon-',
            },
            default: {
                files: {
                    'dist/img/icons.svg': ['src/img/*.svg'],
                }
            }
        },

        svgmin: {
            options: {
                plugins: [
                    { removeViewBox: false },
                    { cleanupIDs: false }
                ]
            },
            dist: {
                files: {
                    'dist/img/icons.svg': 'dist/img/icons.svg'
                }
            }
        },

        'string-replace': {
            dist: {
                files: {
                    'dist/js/glb.share.js': 'dist/js/glb.share.js'
                },
                options: {
                    replacements: [{
                        pattern: '[[X_SVG_X]]',
                        replacement: grunt.file.read('dist/img/icons.svg'),
                    }]
                },
            }
        },

        jasmine: {
            share: {
                src: 'src/js/share.js',
                options: {
                    specs: 'tests/*.spec.js',
                    vendor: [],
                    junit: {
                        path: 'tests/reports/',
                        consolidate: true
                    },
                    keepRunner: true,
                    template: require('grunt-template-jasmine-istanbul'),
                    templateOptions: {
                        coverage: 'tests/reports/coverage.json',
                        report: 'tests/reports'
                    },
                    // phantom options
                    '--web-security' : false,
                    '--local-to-remote-url-access' : true,
                    '--ignore-ssl-errors' : true
                }
            }
        },

        watch: {
            gruntfile: {
                files: '<%= jshint.gruntfile.src %>',
                tasks: ['jshint:gruntfile']
            },
            test: {
                files: '<%= jshint.test.src %>',
                tasks: ['jstest']
            },
            buildJS: {
                files: ['<%= concat.js.src %>'],
                tasks: ['js']
            },
            buildCSS: {
                files: ['src/sass/*.scss'],
                tasks: ['css']
            },
            buildIcons: {
                files: ['src/img/*.svg'],
                tasks: ['icon']
            }
        },

        connect: {
            server: {
               options: {
                    port: 9002,
                    base: '.',
                    livereload: true
               }
            }
        },

        webfont: {
            icons: {
                src: 'src/img/*.svg',
                dest: 'src/fonts',
                destCss: 'src/sass',
                options: {
                    font: 'share-icon',
                    hashes: false,
                    htmlDemo: false,
                    stylesheet: 'scss',
                    embed: ['woff', 'ttf'],
                    templateOptions: {
                        baseClass: 'share-font',
                        classPrefix: 'ico-share-',
                        mixinPrefix: 'ico-share-'
                    },
                    types: 'woff,ttf'
                }
            },
        },

        buddyjs: {
            src: ['<%= concat.js.src %>'],
            options: {}
        }
    });

    // These plugins provide necessary tasks.
    grunt.loadNpmTasks('grunt-webfont');
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-jasmine');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-svgstore');
    grunt.loadNpmTasks('grunt-string-replace');
    grunt.loadNpmTasks('grunt-svgmin');
    grunt.loadNpmTasks('grunt-buddyjs');

    // Custom tasks
    grunt.registerTask('icon', ['svgstore', 'webfont', 'svgmin', 'string-replace']);
    grunt.registerTask('jstest', ['jshint', 'buddyjs', 'jasmine']);
    grunt.registerTask('js', ['concat:js','string-replace', 'uglify']);
    grunt.registerTask('css', ['compass', 'concat:css','cssmin']);

    // Default task.
    grunt.registerTask('default', ['icon', 'jstest', 'js', 'css']);
    grunt.registerTask('server', ['connect:server', 'watch']);
};
<commit_msg>Criada task de bump para lançar release<commit_after>/*global require, module:false */
module.exports = function(grunt) {
    var distJs = 'dist/js/',
        distCss = 'dist/css/';

    // Project configuration.
    grunt.initConfig({
        // Metadata.
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',

        // Task configuration.
        concat: {
            options: {
                banner: '<%= banner %>',
                stripBanners: true
            },
            js: {
                src: ['src/js/*.js'],
                dest: distJs + '<%= pkg.name %>.js'
            },
            css: {
                src: ['src/css/*.css'],
                dest: distCss + '<%= pkg.name %>.css'
            }
        },

        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            dist: {
                src: '<%= concat.js.dest %>',
                dest: distJs + '<%= pkg.name %>.min.js'
            }
        },

        cssmin: {
            minify: {
                src: 'dist/css/glb.share.css',
                dest: 'dist/css/glb.share.min.css',
                banner: '<%= banner %>'
            }
        },

        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                unused: true,
                boss: true,
                eqnull: true,
                browser: true,
                globals: {}
            },
            gruntfile: {
                src: 'Gruntfile.js'
            },
            test: {
                src: ['<%= concat.js.src %>', 'tests/*.spec.js']
            }
        },

        compass: {
            dist: {
                options: {
                    sassDir: 'src/sass',
                    cssDir: 'src/css',
                    outputStyle: 'compressed',
                    noLineComments: true,
                    relativeAssets: true

                }
            }
        },

        svgstore: {
            options: {
                prefix : 'icon-',
            },
            default: {
                files: {
                    'dist/img/icons.svg': ['src/img/*.svg'],
                }
            }
        },

        svgmin: {
            options: {
                plugins: [
                    { removeViewBox: false },
                    { cleanupIDs: false }
                ]
            },
            dist: {
                files: {
                    'dist/img/icons.svg': 'dist/img/icons.svg'
                }
            }
        },

        'string-replace': {
            dist: {
                files: {
                    'dist/js/glb.share.js': 'dist/js/glb.share.js'
                },
                options: {
                    replacements: [{
                        pattern: '[[X_SVG_X]]',
                        replacement: grunt.file.read('dist/img/icons.svg'),
                    }]
                },
            }
        },

        jasmine: {
            share: {
                src: 'src/js/share.js',
                options: {
                    specs: 'tests/*.spec.js',
                    vendor: [],
                    junit: {
                        path: 'tests/reports/',
                        consolidate: true
                    },
                    keepRunner: true,
                    template: require('grunt-template-jasmine-istanbul'),
                    templateOptions: {
                        coverage: 'tests/reports/coverage.json',
                        report: 'tests/reports'
                    },
                    // phantom options
                    '--web-security' : false,
                    '--local-to-remote-url-access' : true,
                    '--ignore-ssl-errors' : true
                }
            }
        },

        watch: {
            gruntfile: {
                files: '<%= jshint.gruntfile.src %>',
                tasks: ['jshint:gruntfile']
            },
            test: {
                files: '<%= jshint.test.src %>',
                tasks: ['jstest']
            },
            buildJS: {
                files: ['<%= concat.js.src %>'],
                tasks: ['js']
            },
            buildCSS: {
                files: ['src/sass/*.scss'],
                tasks: ['css']
            },
            buildIcons: {
                files: ['src/img/*.svg'],
                tasks: ['icon']
            }
        },

        connect: {
            server: {
               options: {
                    port: 9002,
                    base: '.',
                    livereload: true
               }
            }
        },

        webfont: {
            icons: {
                src: 'src/img/*.svg',
                dest: 'src/fonts',
                destCss: 'src/sass',
                options: {
                    font: 'share-icon',
                    hashes: false,
                    htmlDemo: false,
                    stylesheet: 'scss',
                    embed: ['woff', 'ttf'],
                    templateOptions: {
                        baseClass: 'share-font',
                        classPrefix: 'ico-share-',
                        mixinPrefix: 'ico-share-'
                    },
                    types: 'woff,ttf'
                }
            },
        },

        buddyjs: {
            src: ['<%= concat.js.src %>'],
            options: {}
        },

        bump: {
            options: {
                files: ['package.json'],
                updateConfigs: [],
                commit: true,
                commitMessage: 'Release version: %VERSION%',
                commitFiles: ['package.json'],
                createTag: true,
                tagName: '%VERSION%',
                tagMessage: 'Version %VERSION%',
                push: true,
                pushTo: 'upstream',
                gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
            }
        }
    });

    // These plugins provide necessary tasks.
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-jasmine');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-webfont');
    grunt.loadNpmTasks('grunt-svgstore');
    grunt.loadNpmTasks('grunt-string-replace');
    grunt.loadNpmTasks('grunt-svgmin');
    grunt.loadNpmTasks('grunt-buddyjs');
    grunt.loadNpmTasks('grunt-bump');

    // Custom tasks
    grunt.registerTask('icon', ['svgstore', 'webfont', 'svgmin', 'string-replace']);
    grunt.registerTask('jstest', ['jshint', 'buddyjs', 'jasmine']);
    grunt.registerTask('js', ['concat:js','string-replace', 'uglify']);
    grunt.registerTask('css', ['compass', 'concat:css','cssmin']);

    // Default task.
    grunt.registerTask('default', ['icon', 'jstest', 'js', 'css']);
    grunt.registerTask('server', ['connect:server', 'watch']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    var path = require("path");
    var exec = require("child_process").exec;
    var esfuzz= require("esfuzz");

    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-mocha-test');

    var moduleCache = {};

    grunt.initConfig({
        build: {
            dev: {
                options: {
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros/disabled.js"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            devContracts: {
                options: {
                    sourceMap: false,
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            release: {
                options: {
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros/disabled.js"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            tests: {
                options: {
                    compileFrom: "./build/lib/sweet"
                },
                src: "test/*.js",
                dest: "build/"
            }
        },
        copy: {
            buildMacros: {
                expand: true,
                flatten: true,
                src: "macros/*",
                dest: "build/macros/"
            },

            scopedEval: {
                expand: true,
                flatten: true,
                src: "lib/scopedEval.js",
                dest: "build/lib/"
            },
            scopedEvalBrowser: {
                expand: true,
                flatten: true,
                src: "lib/scopedEval.js",
                dest: "browser/scripts/"
            },

            browserMacros: {
                expand: true,
                flatten: true,
                src: "macros/*",
                dest: "browser/scripts/"
            },

            browserSrc: {
                expand: true,
                flatten: true,
                src: "src/*",
                dest: "browser/scripts/src/"
            },

            // for source maps support when using debug.js
            nodeSrc: {
                expand: true,
                flatten: true,
                src: "src/*",
                dest: "build/lib/src/"
            },

            dist: {
                expand: true,
                flatten: true,
                src: "build/lib/*.js",
                dest: "lib/"
            },

            testFixtures: {
                expand: true,
                flatten: false,
                cwd: "test/",
                src: "fixtures/**",
                dest: "build/"
            },
            testUnit: {
                src: "test/test_expander_units.js",
                dest: "build/test_expander_units.js"
            }
        },
        mochaTest: {
            test: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/*.js"],
                filter: function(name) {
                    return !/.*test_es6.*/.test(name);
                }
            },
            es6: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/*.js"],
                filter: function(name) {
                    return /.*test_es6.*/.test(name);
                }
            },
            unit: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/test_expander_units.js"]
            }
        },
        jshint: {
            options: {
                eqnull: true,
                evil: true,
                boss: true,
                laxcomma: true,
                shadow: true,
                loopfunc: true,
                validthis: true
            },
            all: ["build/lib/*.js"]
        },
        pandoc: {
            options: {
                pandocOptions: ["--to=html5",
                                "--standalone",
                                "--toc",
                                "--number-sections",
                                "--include-in-header=doc/main/style/main.css"]
            },
            files: {
                expand: true,
                flatten: true,
                src: "doc/main/*.md",
                dest: "doc/main/",
                ext: ".html"
            }
        },
        watch: {
            docs: {
                files: ["doc/**/*.md", "doc/**/*.css"],
                tasks: ["pandoc"]
            },
            sweetjs: {
                files: ["src/*.js", "test/**/*.js", "macros/*"],
                tasks: ["default"]
            }
        }
    });

    grunt.registerMultiTask("pandoc", function() {
        var cb = this.async();
        var options = this.options({});
        var pandocOpts = options.pandocOptions.join(" ");
        this.files.forEach(function(f) {

            f.src.forEach(function(file) {
                var args = ["-o " + f.dest].concat(pandocOpts.slice())
                                          .concat(file);
                exec("pandoc " + args.join(" "), cb);
            });
        });
    });

    grunt.registerTask("clean", function() {
        grunt.file.delete("build/");
    });

    grunt.registerTask("fuzz", function() {
        var sweet = require("./build/lib/sweet");
        var i, iterations = 20;
        try {
            for (i = 0; i < iterations; i++) {
                var code = esfuzz.render(esfuzz.generate({maxDepth: 10}));
                // ignore `with` since we can't handle it anyway
                if (code.indexOf("with") !== -1) continue;
                sweet.compile(code);
            }
            console.log("done fuzzing");
        } catch (e) {
            console.log("On loop " + i + " attempted to expand:");
            console.log(code);
            console.log("\n" + e);
        }
    });

    grunt.registerMultiTask("build", function() {
        var options = this.options({
            modules: [],
            sourceMap: true,
            compileFrom: "./lib/sweet"
        });
        var sweet = require(options.compileFrom);

        var modules = options.modules.map(function(m) {
            return sweet.loadModule(readModule(m));
        });

        this.files.forEach(function(f) {
            var dest = Array.isArray(f.dest) ? f.dest : [f.dest];
            grunt.log.writeln("output to " + dest.join(", "));

            f.src.forEach(function(file) {
                grunt.log.writeln("compiling " + file);

                var code = grunt.file.read(file);
                var output = sweet.compile(code, {
                    sourceMap: options.sourceMap,
                    filename: file,
                    readableNames: true,
                    modules: modules
                });

                dest.forEach(function(dest) {
                    var sourceMappingURL = dest + path.basename(file) + ".map";
                    var outputFile = output.code + "\n//# sourceMappingURL=" + path.basename(file) + ".map";
                    // macro expanded result
                    grunt.file.write(dest + path.basename(file),
                                     outputFile);
                    if (options.sourceMap) {
                        // sourcemap
                        grunt.file.write(sourceMappingURL,
                                         output.sourceMap);

                    }
                });
            });
        });

    });

    grunt.registerTask("dist", ["build:release", "copy:dist"]);

    grunt.registerTask("test", ["build:tests",
                                "copy:testFixtures",
                                "mochaTest:test"]);

    grunt.registerTask("unit", ["build:dev",
                                "copy:scopedEval",
                                "copy:buildMacros",
                                "copy:nodeSrc",
                                "copy:testUnit",
                                "mochaTest:unit"]);

    grunt.registerTask("default", ["clean",
                                   "copy:scopedEval",
                                   "copy:buildMacros",
                                   "build:dev",
                                   "build:tests",
                                   "copy:browserSrc",
                                   "copy:nodeSrc",
                                   "copy:browserMacros",
                                   "copy:scopedEvalBrowser",
                                   "copy:testFixtures",
                                   "mochaTest:test",
                                   "jshint"]);

    grunt.registerTask("contracts", ["clean",
                                     "copy:scopedEval",
                                     "copy:buildMacros",
                                     "build:devContracts",
                                     "build:tests",
                                     "copy:browserSrc",
                                     "copy:nodeSrc",
                                     "copy:browserMacros",
                                     "copy:scopedEvalBrowser",
                                     "copy:testFixtures",
                                     "mochaTest:test",
                                     "jshint"]);

    grunt.registerTask("full", ["default", "mochaTest:es6"]);
    grunt.registerTask("docs", ["pandoc"]);

    function readModule(mod) {
        var path = require.resolve(mod);
        return grunt.file.read(path);
    }
};
<commit_msg>adding task to compile test.js<commit_after>module.exports = function(grunt) {
    var path = require("path");
    var exec = require("child_process").exec;
    var esfuzz= require("esfuzz");

    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-mocha-test');

    var moduleCache = {};

    grunt.initConfig({
        build: {
            dev: {
                options: {
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros/disabled.js"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            devContracts: {
                options: {
                    sourceMap: false,
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            release: {
                options: {
                    compileFrom: "./lib/sweet",
                    modules: ["contracts-js/macros/disabled.js"]
                },
                src: "src/*.js",
                dest: ["build/lib/", "browser/scripts/"]
            },
            tests: {
                options: {
                    compileFrom: "./build/lib/sweet"
                },
                src: "test/*.js",
                dest: "build/"
            },
            single: {
                options: {
                    sourceMap: false,
                    compileFrom: "./build/lib/sweet"
                },
                src: "test.js",
                dest: "build/"
            },
        },
        copy: {
            buildMacros: {
                expand: true,
                flatten: true,
                src: "macros/*",
                dest: "build/macros/"
            },

            scopedEval: {
                expand: true,
                flatten: true,
                src: "lib/scopedEval.js",
                dest: "build/lib/"
            },
            scopedEvalBrowser: {
                expand: true,
                flatten: true,
                src: "lib/scopedEval.js",
                dest: "browser/scripts/"
            },

            browserMacros: {
                expand: true,
                flatten: true,
                src: "macros/*",
                dest: "browser/scripts/"
            },

            browserSrc: {
                expand: true,
                flatten: true,
                src: "src/*",
                dest: "browser/scripts/src/"
            },

            // for source maps support when using debug.js
            nodeSrc: {
                expand: true,
                flatten: true,
                src: "src/*",
                dest: "build/lib/src/"
            },

            dist: {
                expand: true,
                flatten: true,
                src: "build/lib/*.js",
                dest: "lib/"
            },

            testFixtures: {
                expand: true,
                flatten: false,
                cwd: "test/",
                src: "fixtures/**",
                dest: "build/"
            },
            testUnit: {
                src: "test/test_expander_units.js",
                dest: "build/test_expander_units.js"
            }
        },
        mochaTest: {
            test: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/*.js"],
                filter: function(name) {
                    return !/.*test_es6.*/.test(name);
                }
            },
            es6: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/*.js"],
                filter: function(name) {
                    return /.*test_es6.*/.test(name);
                }
            },
            unit: {
                options:{
                    colors: !grunt.option('no-color')
                },
                src: ["build/test_expander_units.js"]
            }
        },
        jshint: {
            options: {
                eqnull: true,
                evil: true,
                boss: true,
                laxcomma: true,
                shadow: true,
                loopfunc: true,
                validthis: true
            },
            all: ["build/lib/*.js"]
        },
        pandoc: {
            options: {
                pandocOptions: ["--to=html5",
                                "--standalone",
                                "--toc",
                                "--number-sections",
                                "--include-in-header=doc/main/style/main.css"]
            },
            files: {
                expand: true,
                flatten: true,
                src: "doc/main/*.md",
                dest: "doc/main/",
                ext: ".html"
            }
        },
        watch: {
            docs: {
                files: ["doc/**/*.md", "doc/**/*.css"],
                tasks: ["pandoc"]
            },
            sweetjs: {
                files: ["src/*.js", "test/**/*.js", "macros/*"],
                tasks: ["default"]
            }
        }
    });

    grunt.registerMultiTask("pandoc", function() {
        var cb = this.async();
        var options = this.options({});
        var pandocOpts = options.pandocOptions.join(" ");
        this.files.forEach(function(f) {

            f.src.forEach(function(file) {
                var args = ["-o " + f.dest].concat(pandocOpts.slice())
                                          .concat(file);
                exec("pandoc " + args.join(" "), cb);
            });
        });
    });

    grunt.registerTask("clean", function() {
        grunt.file.delete("build/");
    });

    grunt.registerTask("fuzz", function() {
        var sweet = require("./build/lib/sweet");
        var i, iterations = 20;
        try {
            for (i = 0; i < iterations; i++) {
                var code = esfuzz.render(esfuzz.generate({maxDepth: 10}));
                // ignore `with` since we can't handle it anyway
                if (code.indexOf("with") !== -1) continue;
                sweet.compile(code);
            }
            console.log("done fuzzing");
        } catch (e) {
            console.log("On loop " + i + " attempted to expand:");
            console.log(code);
            console.log("\n" + e);
        }
    });

    grunt.registerMultiTask("build", function() {
        var options = this.options({
            modules: [],
            sourceMap: true,
            compileFrom: "./lib/sweet"
        });
        var sweet = require(options.compileFrom);

        var modules = options.modules.map(function(m) {
            return sweet.loadModule(readModule(m));
        });

        this.files.forEach(function(f) {
            var dest = Array.isArray(f.dest) ? f.dest : [f.dest];
            grunt.log.writeln("output to " + dest.join(", "));

            f.src.forEach(function(file) {
                grunt.log.writeln("compiling " + file);

                var code = grunt.file.read(file);
                var output = sweet.compile(code, {
                    sourceMap: options.sourceMap,
                    filename: file,
                    readableNames: true,
                    modules: modules
                });

                dest.forEach(function(dest) {
                    var sourceMappingURL = dest + path.basename(file) + ".map";
                    var outputFile = output.code + "\n//# sourceMappingURL=" + path.basename(file) + ".map";
                    // macro expanded result
                    grunt.file.write(dest + path.basename(file),
                                     outputFile);
                    if (options.sourceMap) {
                        // sourcemap
                        grunt.file.write(sourceMappingURL,
                                         output.sourceMap);

                    }
                });
            });
        });

    });

    grunt.registerTask("dist", ["build:release", "copy:dist"]);

    grunt.registerTask("test", ["build:tests",
                                "copy:testFixtures",
                                "mochaTest:test"]);

    grunt.registerTask("unit", ["build:dev",
                                "copy:scopedEval",
                                "copy:buildMacros",
                                "copy:nodeSrc",
                                "copy:testUnit",
                                "mochaTest:unit"]);

    grunt.registerTask("single", ["build:dev",
                                  "copy:scopedEval",
                                  "copy:buildMacros",
                                  "copy:nodeSrc",
                                  "build:single"]);

    grunt.registerTask("default", ["clean",
                                   "copy:scopedEval",
                                   "copy:buildMacros",
                                   "build:dev",
                                   "build:tests",
                                   "copy:browserSrc",
                                   "copy:nodeSrc",
                                   "copy:browserMacros",
                                   "copy:scopedEvalBrowser",
                                   "copy:testFixtures",
                                   "mochaTest:test",
                                   "jshint"]);

    grunt.registerTask("contracts", ["clean",
                                     "copy:scopedEval",
                                     "copy:buildMacros",
                                     "build:devContracts",
                                     "build:tests",
                                     "copy:browserSrc",
                                     "copy:nodeSrc",
                                     "copy:browserMacros",
                                     "copy:scopedEvalBrowser",
                                     "copy:testFixtures",
                                     "mochaTest:test",
                                     "jshint"]);

    grunt.registerTask("full", ["default", "mochaTest:es6"]);
    grunt.registerTask("docs", ["pandoc"]);

    function readModule(mod) {
        var path = require.resolve(mod);
        return grunt.file.read(path);
    }
};
<|endoftext|>