<commit_before>/*
 * grunt-combine
 * https://github.com/mcgaryes/grunt-combine
 * https://github.com/gruntjs/grunt/
 *
 * Copyright (c) 2013 Eric McGary
 * Licensed under the MIT license.
 *
 * @main grunt-combine
 */
module.exports = function (grunt) {

    "use strict";

    var _ = require("underscore");
    var fs = require('fs');

    var starttime = (new Date()).getTime();
    var processedFiles = 0;
    var processed = 0;
    var tokens;
    var input = [];
    var fileContents = [];
    var output;
    var done;
    var timer;
    var cwd;

    /**
     * Main task kick-off functionality
     *
     * @for grunt-combine
     * @method registerMultiTask
     */
    grunt.registerMultiTask('combine', 'Combine files with token based search and replace functionality.', function () {

        // set out defaults
        done = this.async();
        cwd = this.data.cwd;
        input = this.data.input;
        output = this.data.output;
        tokens = this.data.tokens;

        // load the input file as text
        _.each(input, function (elem, index) {
            // check to make sure that we have everything that we need before continuing
            if (_.isUndefined(elem)) {
                grunt.fail.warn('You must specify an input/output.');
            }

            var path = cwd + elem;

            fs.readFile(path, 'utf8', function (e, data) {
                if (e) {
                    grunt.fail.warn('There was an error processing the input file.');
                }

                // run through each of the replacements and load the files if needed. Replace the
                // replacement with the files contents if it happens to be a file
                fileContents[index] = data;

                // now process all of out replacements
                processed = 0;
                processTokens(index);
            });
        });

        // complete the task
        timer = setTimeout(function () {
            grunt.fail.warn('The task has timed out.');
        }, 10000);

        /**
         * Processes all of the passed replacements
         *
         * @for grunt-combine
         * @method processReplacements
         */
        var processTokens = function (inputIndex) {

            _.each(tokens, function (token, index) {

                // determain whether or not this is a file reference or a string
                if (token.file) {

                    // read the file and reset replacement to what was loaded
                    fs.readFile(token.file, 'utf8', function (e, data) {
                        if (e) {
                            grunt.fail.warn("There was an error processing the replacement '" + token.file + "' file.");
                        }
                        tokens[index].contents = data;
                        processCompleteCallback(inputIndex);
                    });

                } else if (token.string) {
                    // we didn't need to load a file
                    tokens[index].contents = token.string;
                    processCompleteCallback(inputIndex);
                } else {
                    processCompleteCallback(inputIndex);
                }

            }, this);
        };

        /**
         * Process completion callback. When all replacements have been processed the actual
         * combining of files takes place.
         *
         * @for grunt-combine
         * @method processCompleteCallback
         */
        var processCompleteCallback = function (inputIndex) {
            processed++;
            if (processed === tokens.length) {
                findAndReplaceTokens(inputIndex);
            }
        };

        /**
         * Looks for the specified token and replaces it with the next replacement
         * in the replacements array.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var findAndReplaceTokens = function (inputIndex) {

            // run through the document and replace anything we can in the input string
            _.each(tokens, function (token) {
                if (token.contents !== undefined) {
                    var position = fileContents[inputIndex].search(token.token);
                    var pre = fileContents[inputIndex].substr(0, position);
                    var post = fileContents[inputIndex].substr(position + token.token.length, fileContents[inputIndex].length);
                    fileContents[inputIndex] = pre + token.contents + post;
                } else {
                    grunt.log.writeln("Replacement failed for token '" + token.token + "'.");
                }
            });

            writeOutput(inputIndex);
        };

        /**
         * Writes the processed input file to the specified output name.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var writeOutput = function (inputIndex) {
            var path = output + input[inputIndex];
            // write the input string to the output file name
            grunt.log.writeln('Writing Output: ' + (path).cyan);
            fs.writeFile(path, fileContents[inputIndex], 'utf8', function (err) {
                if (err) {
                    clearTimeout(timer);
                    grunt.fail.warn("Could not write output '" + output + "' file.");
                }
                var endtime = (new Date()).getTime();
                clearTimeout(timer);
                processedFiles++;
                if (processedFiles === fileContents.length) {
                    done();
                }
            });
        };
    });
};
<commit_msg>Add support to single file input, add support to output as path, add optional cwd.<commit_after>/*
 * grunt-combine
 * https://github.com/mcgaryes/grunt-combine
 * https://github.com/gruntjs/grunt/
 *
 * Copyright (c) 2013 Eric McGary
 * Licensed under the MIT license.
 *
 * @main grunt-combine
 */
module.exports = function (grunt) {

    "use strict";

    var _ = require("underscore");
    var fs = require('fs');

    var starttime = (new Date()).getTime();
    var processedFiles = 0;
    var processed = 0;
    var tokens;
    var input = [];
    var fileContents = [];
    var output;
    var outputIsPath;
    var done;
    var timer;
    var cwd;

    /**
     * Main task kick-off functionality
     *
     * @for grunt-combine
     * @method registerMultiTask
     */
    grunt.registerMultiTask('combine', 'Combine files with token based search and replace functionality.', function () {

        // user input is an array - treat output as a path
        if (Array.isArray(this.data.input)) {
            input = this.data.input;
        }
        else {
            input[0] = this.data.input;
        }

        // set out defaults
        done = this.async();
        cwd = this.data.cwd;
        output = this.data.output;
        outputIsPath = output.charAt(output.length - 1) == '/';
        tokens = this.data.tokens;

        // load the input file as text
        _.each(input, function (elem, index) {
            // check to make sure that we have everything that we need before continuing
            if (_.isUndefined(elem)) {
                grunt.fail.warn('You must specify an input/output.');
            }

            var path = cwd ? cwd + elem : elem;

            fs.readFile(path, 'utf8', function (e, data) {
                if (e) {
                    grunt.fail.warn('There was an error processing the input file.');
                }

                // run through each of the replacements and load the files if needed. Replace the
                // replacement with the files contents if it happens to be a file
                grunt.log.writeln('Processing Input: ' + (elem).cyan);
                fileContents[index] = data;

                // now process all of out replacements
                processed = 0;
                processTokens(index);
            });
        });

        // complete the task
        timer = setTimeout(function () {
            grunt.fail.warn('The task has timed out.');
        }, 10000);

        /**
         * Processes all of the passed replacements
         *
         * @for grunt-combine
         * @method processReplacements
         */
        var processTokens = function (inputIndex) {

            _.each(tokens, function (token, index) {

                // determain whether or not this is a file reference or a string
                if (token.file) {

                    // read the file and reset replacement to what was loaded
                    fs.readFile(token.file, 'utf8', function (e, data) {
                        if (e) {
                            grunt.fail.warn("There was an error processing the replacement '" + token.file + "' file.");
                        }
                        tokens[index].contents = data;
                        processCompleteCallback(inputIndex);
                    });

                } else if (token.string) {
                    // we didn't need to load a file
                    tokens[index].contents = token.string;
                    processCompleteCallback(inputIndex);
                } else {
                    processCompleteCallback(inputIndex);
                }

            }, this);
        };

        /**
         * Process completion callback. When all replacements have been processed the actual
         * combining of files takes place.
         *
         * @for grunt-combine
         * @method processCompleteCallback
         */
        var processCompleteCallback = function (inputIndex) {
            processed++;
            if (processed === tokens.length) {
                findAndReplaceTokens(inputIndex);
            }
        };

        /**
         * Looks for the specified token and replaces it with the next replacement
         * in the replacements array.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var findAndReplaceTokens = function (inputIndex) {

            // run through the document and replace anything we can in the input string
            _.each(tokens, function (token) {
                if (token.contents !== undefined) {
                    var position = fileContents[inputIndex].search(token.token);
                    var pre = fileContents[inputIndex].substr(0, position);
                    var post = fileContents[inputIndex].substr(position + token.token.length, fileContents[inputIndex].length);
                    fileContents[inputIndex] = pre + token.contents + post;
                } else {
                    grunt.log.writeln("Replacement failed for token '" + token.token + "'.");
                }
            });

            writeOutput(inputIndex);
        };

        /**
         * Writes the processed input file to the specified output name.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var writeOutput = function (inputIndex) {
            var path = outputIsPath ? output + input[inputIndex] : output;
            // write the input string to the output file name
            grunt.log.writeln('Writing Output: ' + (path).cyan);
            fs.writeFile(path, fileContents[inputIndex], 'utf8', function (err) {
                if (err) {
                    clearTimeout(timer);
                    grunt.fail.warn("Could not write output '" + output + "' file.");
                }
                var endtime = (new Date()).getTime();
                grunt.log.writeln('Combine task completed in ' + ((endtime - starttime) / 1000) + ' seconds');
                clearTimeout(timer);
                processedFiles++;
                if (processedFiles === fileContents.length) {
                    processedFiles = 0;
                    fileContents = [];
                    done();
                }
            });
        };
    });
};
<|endoftext|>


<commit_before>/*
 * grunt-csp-express
 * https://github.com/dietercastel/grunt-csp-express
 *
 * Copyright (c) 2015 Dieter Castel
 * Licensed under the MIT license.
 */

'use strict';
var sh = require('execSync');
var util = require('util');
var description = 'Creates a csp.json file to be used with content-security-policy.';
var noExpressDir ="Set the expressDir option in your Gruntfile.js to a valid path.";

//Options as used by content-security-policy
// Other options are:
// policy["report-only"]
// var otheroptions = ["report-uri", "sandbox", ];
var srcs = ["default-src",
	"script-src",
	"object-src",
	"style-src",
	"img-src",
	"media-src",
	"frame-src",
	"font-src",
	"connect-src" ];

//Regex related declarations.
var selfRegex=/( src=| href=){1}("|')((\/)?[^:]+(\/)?)+("|')/i;
var httpRegex=/http:\/\/[a-z0-9-]+((\.[a-z0-9-]+)*)+(:[0-9]+)?(\/)?/i;
var httpsRegex=/https:\/\/[a-z0-9-]+((\.[a-z0-9-]+)*)+(:[0-9]+)?(\/)?/i;

function onlyUnique(value, index, self) {
	return self.indexOf(value) === index;
}

module.exports = function(grunt) {

	grunt.registerMultiTask('makecsp', description, function() {
		//This are the prototypical options
		//Can be overridden by gruntfile
		var options = this.options({
			filename: "/csp.json",
			excludeDirs: ["bin","node_modules",".git","test"],
			excludeFiles: ["csp.json,Gruntfile.js,package.json,.gitignore"],
			expressDir: ".",
			extraRegexs: { //For each tag an optional extra regex.
				"default-src":"url\\\(",
				"script-src":"",
				"object-src":"",
				"style-src":"<link rel=.stylesheet",
				"img-src":"",
				"media-src":"",
				"frame-src":"<iframe (ng-)?src=",
				"font-src":"",
				"connect-src": "url:" // add $resource ?
				}
		});

		//Check whether a proper path is set.
		if(options["expressDir"] === undefined){
			//Might include actual fs.exists here.
			grunt.log.error(noExpressDir);
			grunt.fail.fatal(noExpressDir);
			return;
		}

		grunt.log.writeln("Running makecsp with:\n" + util.inspect(options));

		var policy = {};

		var basecommand ='grep -Er ';

		//Due to some strange error --exclude-dir={i1,i2,i3} does not work.
		var exDirRes = "";
		options["excludeDirs"].forEach(function(ex){
			exDirRes += '--exclude-dir="'+ ex + '" ';
		});

		//But for normal files the alternative doesn't work
		// var exFilesRes = "";
		// options["excludeFiles"].forEach(function(ex){
		// exFilesRes += '--exclude="'+ ex + '" ';
		// });

		// This worked for normal files
		// var basecommand ='grep -Er --exclude-dir={'+
		// options['excludeDirs'].toString() +
		// '} --exclude={'+
		// options['excludeFiles'].toString()+
		// '}';

		//Handeling the wildcard is pretty hard apperantly...
		basecommand += exDirRes + '--exclude="*.log" ' + '--exclude={'+ options['excludeFiles'].toString()+ '}';
			grunt.log.writeln("basecommand ="+ basecommand);

			//Iterate over all options and look for tags related to the option.
			srcs.forEach(function(src) {
				//Extract tag except for default-src
				var tag = src.substring(0,src.length-4);
				var baseTagRegex ='<'+tag+' (ng-)?src=';
				if(src === "default-src"){
					baseTagRegex ='<link rel=.import';
				}
				//Process extra regexs
				var extraRegex= "";
				if(options["extraRegexs"][src] !== ""){
					extraRegex = "|"+options["extraRegexs"][src];
				}
				var tagregex = baseTagRegex+extraRegex;
				grunt.log.writeln("\nTag: " + tag);
				grunt.log.writeln("Tagregex=" + tagregex);

				// Build and run the grep command.
				// Space plus open double quote
				var startRegexArg =' "';
				// Close double quote plus space
				var endRegexArg ='" ';
				var runCommand = basecommand + startRegexArg + tagregex + endRegexArg + options["expressDir"];
				var returnObject = sh.exec(runCommand);
				var stdout = returnObject.stdout;

				//Proccess each found line looking for urls.
				var addSelf = false;
				if(src==="connect-src"){
					//Loading angular templates from self!!
					addSelf = true;
				}
				var matchedHTTP = [];
				var matchedHTTPS = [];
				grunt.verbose.writeln('Checking:\n'+ runCommand);
				grunt.verbose.writeln('Output:');
				grunt.verbose.writeln("____________________________________________________________________");
				grunt.verbose.write(stdout);
				grunt.verbose.writeln("========Iteratation over each line=======");
				stdout.split(/\r?\n/).forEach(function (line) {
					grunt.verbose.writeln("matching http:");
					grunt.verbose.write(line);
					var httpRes = line.match(httpRegex);
					grunt.verbose.writeln(httpRes);
					if(httpRes !== null){
						matchedHTTP = matchedHTTP.concat(httpRes[0]);
						grunt.verbose.write(matchedHTTP);
					}
					grunt.verbose.writeln("matching https:");
					grunt.verbose.write(line);
					var httpsRes = line.match(httpsRegex);
					grunt.verbose.writeln(httpsRes);
					if(httpsRes !== null){
						matchedHTTPS = matchedHTTPS.concat(httpsRes[0]);
						grunt.verbose.write(matchedHTTPS);
					}
					grunt.verbose.writeln("matching self:");
					var selfRes= line.match(selfRegex);
					grunt.verbose.writeln(selfRes);
					if(selfRes !== null){
						addSelf = true;
					}
				});
				grunt.verbose.writeln("____________________________________________________________________");
				grunt.log.writeln("matchedHTTP:" + matchedHTTP);
				grunt.log.writeln("matchedHTTPS:" + matchedHTTPS);
				var allURLs;
				if(matchedHTTPS === undefined ){
					allURLs = matchedHTTP;
				}else{
					if(matchedHTTP === undefined){
						var errorString = "No urls found";
						grunt.log.error(errorString);
						grunt.fail.warn(errorString);
					} else {
						allURLs = matchedHTTPS.concat(matchedHTTP);
					}
				}
				if(addSelf){
					allURLs = ["'self'"].concat(allURLs);
				}
				grunt.verbose.writeln("allURLs (non-uniqued)" + allURLs);
				if(allURLs.length !== 0){
					policy[src] = allURLs.filter(onlyUnique);
				}
				grunt.verbose.write("Policy so far: " + util.inspect(policy));
				grunt.verbose.writeln("Matched HTTPS: "+ matchedHTTP);
				grunt.verbose.writeln("#WARNING# Matched HTTP (UNSECURE CONNECTION): "+ matchedHTTP);
				//Mention line numbers of HTTP resources?
			});
			//Create a nice json from it and write it to disk
			var stringJson = JSON.stringify(policy, null, 4);
			//DONT TRY TO WRITE WITH fs while using grunt!!!!
			grunt.log.writeln("Found policy: " + stringJson);
			var outputFilename = options["expressDir"]+options["filename"];
			grunt.file.write(outputFilename, stringJson);
			grunt.log.ok("File written to: " + outputFilename);
		});
	};
<commit_msg>Added warnings, fixed default to be more restrictive.<commit_after>/*
 * grunt-csp-express
 * https://github.com/dietercastel/grunt-csp-express
 *
 * Copyright (c) 2015 Dieter Castel
 * Licensed under the MIT license.
 */

'use strict';
var sh = require('execSync');
var util = require('util');
var description = 'Creates a csp.json file to be used with content-security-policy.';
var noExpressDir ="Set the expressDir option in your Gruntfile.js to a valid path.";

//Options as used by content-security-policy
// Other options are:
// policy["report-only"]
// var otheroptions = ["report-uri", "sandbox", ];
var srcs = [
// "default-src",
	"script-src",
	"object-src",
	"style-src",
	"img-src",
	"media-src",
	"frame-src",
	"font-src",
	"connect-src" ];

//Regex related declarations.
var selfRegex=/( src=| href=){1}("|')((\/)?[^:]+(\/)?)+("|')/i;
var httpRegex=/http:\/\/[a-z0-9-]+((\.[a-z0-9-]+)*)+(:[0-9]+)?(\/)?/i;
var httpsRegex=/https:\/\/[a-z0-9-]+((\.[a-z0-9-]+)*)+(:[0-9]+)?(\/)?/i;

var inlinescript = {
	"regex" : "<script>",
	"message" : "You are using inline script(s) which is bad practice and will break when using CSP." +
		"\n Extract the inline script(s) into (a) seperate file(s) and include those.",
	"extraflag" : " -w"
};
var inlinestyle = {
	"regex" : "<style>",
	"message" : "You are using inline style(s) which is bad practice and will break when using CSP." +
		"\n Extract the inline style(s) into (a) seperate file(s) and include those.",
	"extraflag" : " -w"
};
var htmlimport = {
	"regex" : "<link rel=.import|ng-include",
	"message" : "You are using html import(s) which could lead to a CSP circumvention in chrome!",
	"extraflag" : ""
};

var warnings =  [
	inlinescript,
	inlinestyle,
	htmlimport
];

function onlyUnique(value, index, self) {
	return self.indexOf(value) === index;
}

module.exports = function(grunt) {

	grunt.registerMultiTask('makecsp', description, function() {
		//This are the prototypical options
		//Can be overridden by gruntfile
		var options = this.options({
			filename: "/csp.json",
			excludeDirs: ["bin","node_modules",".git","test"],
			excludeFiles: ["csp.json,Gruntfile.js,package.json,.gitignore"],
			expressDir: ".",
			extraRegexs: { //For each tag an optional extra regex.
				// "default-src":"url\\\(",
				"script-src":"",
				"object-src":"",
				"style-src":"<link rel=.stylesheet",
				"img-src":"",
				"media-src":"",
				"frame-src":"<iframe (ng-)?src=",
				"font-src":"",
				"connect-src": "url:" // add $resource ?
				}
		});

		//Check whether a proper path is set.
		if(options["expressDir"] === undefined){
			//Might include actual fs.exists here.
			grunt.log.error(noExpressDir);
			grunt.fail.fatal(noExpressDir);
			return;
		}
		grunt.log.writeln("Running makecsp with:\n" + util.inspect(options));

		var policy = {
		"default-src" : "'none'"
		};

		var basecommand ='grep -Enr ';

		//Due to some strange error --exclude-dir={i1,i2,i3} does not work.
		var exDirRes = "";
		options["excludeDirs"].forEach(function(ex){
			exDirRes += '--exclude-dir="'+ ex + '" ';
		});

		//But for normal files the alternative doesn't work
		// var exFilesRes = "";
		// options["excludeFiles"].forEach(function(ex){
		// exFilesRes += '--exclude="'+ ex + '" ';
		// });

		// This worked for normal files
		// var basecommand ='grep -Er --exclude-dir={'+
		// options['excludeDirs'].toString() +
		// '} --exclude={'+
		// options['excludeFiles'].toString()+
		// '}';

		//Handeling the wildcard is pretty hard apperantly...
		basecommand += exDirRes + '--exclude="*.log" ' + '--exclude={'+ options['excludeFiles'].toString()+ '}';
		var startRegexArg =' "';
		// Close double quote plus space
		var endRegexArg ='" ';
		grunt.log.writeln("basecommand ="+ basecommand);

		//Iterate over all options and look for tags related to the option.
		srcs.forEach(function(src) {
			//Extract tag except for default-src
			var tag = src.substring(0,src.length-4);
			var baseTagRegex ='<'+tag+' (ng-)?src=';
			// if(src === "default-src"){
			// 	baseTagRegex ='<link rel=.import|ng-include';
			// }
			//Process extra regexs
			var extraRegex= "";
			if(options["extraRegexs"][src] !== ""){
				extraRegex = "|"+options["extraRegexs"][src];
			}
			var tagregex = baseTagRegex+extraRegex;
			grunt.log.writeln("\nTag: " + tag);
			grunt.log.writeln("Tagregex=" + tagregex);

			// Build and run the grep command.
			// Space plus open double quote
			var runCommand = basecommand + startRegexArg + tagregex + endRegexArg + options["expressDir"];
			var returnObject = sh.exec(runCommand);
			var stdout = returnObject.stdout;

			//Proccess each found line looking for urls.
			var addSelf = false;
			if(src==="connect-src"){
				//Loading angular templates from self!!
				addSelf = true;
			}
			var matchedHTTP = [];
			var matchedHTTPS = [];
			grunt.verbose.writeln('Checking:\n'+ runCommand);
			grunt.verbose.writeln('Output:');
			grunt.verbose.writeln("____________________________________________________________________");
			grunt.verbose.write(stdout);
			grunt.verbose.writeln("========Iteratation over each line=======");
			stdout.split(/\r?\n/).forEach(function (line) {
				grunt.verbose.writeln("matching http:");
				grunt.verbose.write(line);
				var httpRes = line.match(httpRegex);
				grunt.verbose.writeln(httpRes);
				if(httpRes !== null){
					matchedHTTP = matchedHTTP.concat(httpRes[0]);
					grunt.verbose.write(matchedHTTP);
				}
				grunt.verbose.writeln("matching https:");
				grunt.verbose.write(line);
				var httpsRes = line.match(httpsRegex);
				grunt.verbose.writeln(httpsRes);
				if(httpsRes !== null){
					matchedHTTPS = matchedHTTPS.concat(httpsRes[0]);
					grunt.verbose.write(matchedHTTPS);
				}
				grunt.verbose.writeln("matching self:");
				var selfRes= line.match(selfRegex);
				grunt.verbose.writeln(selfRes);
				if(selfRes !== null){
					addSelf = true;
				}
			});
			grunt.verbose.writeln("____________________________________________________________________");
			if(matchedHTTP.length !== 0){
				grunt.log.writeln("WARNING: Matched HTTP (UNSECURE CONNECTION): "['red']);
				grunt.log.writeln(matchedHTTP['red']);
			}
			grunt.log.writeln("matchedHTTPS:" + matchedHTTPS);
			var allURLs;
			if(matchedHTTPS === []){
				allURLs = matchedHTTP;
			}else{
				if(matchedHTTP === []){
					var errorString = "No urls found";
					grunt.log.error(errorString);
					grunt.fail.warn(errorString);
				} else {
					allURLs = matchedHTTPS.concat(matchedHTTP);
				}
			}
			if(addSelf){
				allURLs = ["'self'"].concat(allURLs);
			}
			grunt.verbose.writeln("allURLs (non-uniqued)" + allURLs);
			if(allURLs.length !== 0){
				policy[src] = allURLs.filter(onlyUnique);
			}
			grunt.verbose.write("Policy so far: " + util.inspect(policy));
			//Mention line numbers of HTTP resources?
		});
		//Create a nice json from it and write it to disk
		var stringJson = JSON.stringify(policy, null, 4);
		//DONT TRY TO WRITE WITH fs while using grunt!!!!
		grunt.log.writeln("Found policy: " + stringJson ['green']);
		var outputFilename = options["expressDir"]+options["filename"];
		grunt.file.write(outputFilename, stringJson);
		grunt.log.ok("File written to: " + outputFilename);

		// basecommand += exDirRes + '--exclude="*.log" ' + '--exclude={'+ options['excludeFiles'].toString()+ '}';
		// var startRegexArg =' "';
		// // Close double quote plus space
		// var endRegexArg ='" ';

		warnings.forEach(function(warning){
			var runCommand = basecommand + startRegexArg + warning["regex"] + endRegexArg + options["expressDir"] + warning.extraflag;
			var returnObject = sh.exec(runCommand);
			if(returnObject.code === 0){
				var stdout = returnObject.stdout;
				grunt.log.writeln("WARNING: "['red'].bold +warning["message"] ['red'].bold);
				stdout.split(/\r?\n/).forEach(function(line){
					grunt.log.writeln(line ['yellow']);
				});
				grunt.log.writeln("____________________________________________________________________" ['red']);
			}
		});

	});
};
<|endoftext|>


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

    'use strict';

    var spawn = require('child_process').spawn,
        path = require('path'),
        async = require('async'),
        fs = require('fs');

    var _ = grunt.util._;

    var versions = {
        1.0: '1.0.3705',
        1.1: '1.1.4322',
        2.0: '2.0.50727',
        3.5: '3.5',
        4.0: '4.0.30319',
        12.0: '12.0',
        14.0: '14.0'
    };

    grunt.registerMultiTask('msbuild', 'Run MSBuild tasks', function() {

        var asyncCallback = this.async();

        var options = this.options({
            targets: ['Build'],
            buildParameters: {},
            failOnError: true,
            verbosity: 'normal',
            processor: '',
            nologo: true
        });

        if (!options.projectConfiguration) {
            options.projectConfiguration = 'Release';
        }

        grunt.verbose.writeln('Using Options: ' + JSON.stringify(options, null, 4).cyan);

        var projectFunctions = [];
        var files = this.files;

        if (files.length == 0) {
            files.push({src: ['']});
        }

        files.forEach(function(filePair) {
            filePair.src.forEach(function(src) {
                projectFunctions.push(function(cb) {
                    build(src, options, cb);
                });

                projectFunctions.push(function(cb) {
                    cb();
                });
            });
        });

        async.series(projectFunctions, function() {
            asyncCallback();
        });

    });

    function build(src, options, cb) {

        var projName = src || path.basename(process.cwd());

        grunt.log.writeln('Building ' + projName.cyan);

        var cmd = createCommand(options.version || null, options.processor);
        var args = createCommandArgs(src, options);

        grunt.verbose.writeln('Using cmd:', cmd);
        grunt.verbose.writeln('Using args:', args);

        if (!cmd) {
            return;
        }

        var cp = spawn(cmd, args, {
            stdio: 'inherit'
        });

        cp.on('close', function(code) {
            var success = code === 0;
            grunt.verbose.writeln('close received - code: ', success);

            if (code === 0) {
                grunt.log.writeln('Build complete ' + projName.cyan);
                cb();
            } else {
                grunt.log.writeln(('MSBuild failed with code: ' + code).cyan + projName);
                if (options.failOnError) {
                    grunt.warn('MSBuild exited with a failure code: ' + code);
                }
            }

        });

    }

    function createCommandArgs(src, options) {

        var args = [];

        if (src) {
            var projectPath = path.normalize(path.resolve() + '/' + src);

            args.push(projectPath);
        }

        args.push('/target:' + options.targets);
        args.push('/verbosity:' + options.verbosity);

        if (options.nologo) {
            args.push('/nologo');
        }

        if (options.maxCpuCount) {
            grunt.verbose.writeln('Using maxcpucount:', +options.maxCpuCount);
            args.push('/maxcpucount:' + options.maxCpuCount);
        }

	if (options.consoleLoggerParameters) {
            grunt.verbose.writeln('Using clp:' + options.consoleLoggerParameters);
	    args.push('/clp:' + options.consoleLoggerParameters);
	}

        args.push('/property:Configuration=' + options.projectConfiguration);

        if (options.platform) {
            args.push('/p:Platform=' + options.platform);
        }

        for (var buildArg in options.buildParameters) {
            args.push('/property:' + buildArg + '=' + options.buildParameters[buildArg]);
        }

        return args;
    }

    function createCommand(version, processor) {

        // temp mono xbuild usage for linux / osx - assumes xbuild is in the path, works on my machine...
        if (process.platform === 'linux' || process.platform === 'darwin') {
            return 'xbuild';
        }

        var programFiles = process.env['ProgramFiles(x86)'] || process.env.PROGRAMFILES;

        if (!version) {
            version = 4.0; // default fallback to version 4.0

            var msbuildDir = path.join(programFiles, 'MSBuild');

            if (fs.existsSync(msbuildDir)) {
                var msbuildVersions = fs.readdirSync(msbuildDir)
                    .filter(function(entryName) {
                        return entryName.indexOf('1') === 0;
                    });

                if (msbuildVersions.length > 0) {
                    // set latest installed msbuild version
                    version = parseInt(msbuildVersions[msbuildVersions.length - 1]);
                }
            }
        }

        var specificVersion = versions[version];

        if (!specificVersion) {
            grunt.fatal('Unrecognised MSBuild version "' + version + '"');
        }

        if (version < 12) {
            var frameworkDir = 'Framework' + (processor === 64 ? processor : '');
            var buildExecutablePath = path.join(process.env.WINDIR, 'Microsoft.Net', frameworkDir, 'v' + specificVersion, 'MSBuild.exe');
        } else {
            var x64Dir = processor === 64 ? 'amd64' : '';
            var buildExecutablePath = path.join(programFiles, 'MSBuild', specificVersion, 'Bin', x64Dir, 'MSBuild.exe');
        }

        grunt.verbose.writeln('Using MSBuild at:' + buildExecutablePath.cyan);

        if (!fs.existsSync(buildExecutablePath)) {
            grunt.fatal('Unable to find MSBuild executable');
        }

        return path.normalize(buildExecutablePath);

    }

};
<commit_msg>Use parseFloat for msbuild versions<commit_after>module.exports = function(grunt) {

    'use strict';

    var spawn = require('child_process').spawn,
        path = require('path'),
        async = require('async'),
        fs = require('fs');

    var _ = grunt.util._;

    var versions = {
        1.0: '1.0.3705',
        1.1: '1.1.4322',
        2.0: '2.0.50727',
        3.5: '3.5',
        4.0: '4.0.30319',
        12.0: '12.0',
        14.0: '14.0'
    };

    grunt.registerMultiTask('msbuild', 'Run MSBuild tasks', function() {

        var asyncCallback = this.async();

        var options = this.options({
            targets: ['Build'],
            buildParameters: {},
            failOnError: true,
            verbosity: 'normal',
            processor: '',
            nologo: true
        });

        if (!options.projectConfiguration) {
            options.projectConfiguration = 'Release';
        }

        grunt.verbose.writeln('Using Options: ' + JSON.stringify(options, null, 4).cyan);

        var projectFunctions = [];
        var files = this.files;

        if (files.length == 0) {
            files.push({src: ['']});
        }

        files.forEach(function(filePair) {
            filePair.src.forEach(function(src) {
                projectFunctions.push(function(cb) {
                    build(src, options, cb);
                });

                projectFunctions.push(function(cb) {
                    cb();
                });
            });
        });

        async.series(projectFunctions, function() {
            asyncCallback();
        });

    });

    function build(src, options, cb) {

        var projName = src || path.basename(process.cwd());

        grunt.log.writeln('Building ' + projName.cyan);

        var cmd = createCommand(options.version || null, options.processor);
        var args = createCommandArgs(src, options);

        grunt.verbose.writeln('Using cmd:', cmd);
        grunt.verbose.writeln('Using args:', args);

        if (!cmd) {
            return;
        }

        var cp = spawn(cmd, args, {
            stdio: 'inherit'
        });

        cp.on('close', function(code) {
            var success = code === 0;
            grunt.verbose.writeln('close received - code: ', success);

            if (code === 0) {
                grunt.log.writeln('Build complete ' + projName.cyan);
                cb();
            } else {
                grunt.log.writeln(('MSBuild failed with code: ' + code).cyan + projName);
                if (options.failOnError) {
                    grunt.warn('MSBuild exited with a failure code: ' + code);
                }
            }

        });

    }

    function createCommandArgs(src, options) {

        var args = [];

        if (src) {
            var projectPath = path.normalize(path.resolve() + '/' + src);

            args.push(projectPath);
        }

        args.push('/target:' + options.targets);
        args.push('/verbosity:' + options.verbosity);

        if (options.nologo) {
            args.push('/nologo');
        }

        if (options.maxCpuCount) {
            grunt.verbose.writeln('Using maxcpucount:', +options.maxCpuCount);
            args.push('/maxcpucount:' + options.maxCpuCount);
        }

	if (options.consoleLoggerParameters) {
            grunt.verbose.writeln('Using clp:' + options.consoleLoggerParameters);
	    args.push('/clp:' + options.consoleLoggerParameters);
	}

        args.push('/property:Configuration=' + options.projectConfiguration);

        if (options.platform) {
            args.push('/p:Platform=' + options.platform);
        }

        for (var buildArg in options.buildParameters) {
            args.push('/property:' + buildArg + '=' + options.buildParameters[buildArg]);
        }

        return args;
    }

    function createCommand(version, processor) {

        // temp mono xbuild usage for linux / osx - assumes xbuild is in the path, works on my machine...
        if (process.platform === 'linux' || process.platform === 'darwin') {
            return 'xbuild';
        }

        var programFiles = process.env['ProgramFiles(x86)'] || process.env.PROGRAMFILES;

        if (!version) {
            version = 4.0; // default fallback to version 4.0

            var msbuildDir = path.join(programFiles, 'MSBuild');

            if (fs.existsSync(msbuildDir)) {
                var msbuildVersions = fs.readdirSync(msbuildDir)
                    .filter(function(entryName) {
                        return entryName.indexOf('1') === 0;
                    });

                if (msbuildVersions.length > 0) {
                    // set latest installed msbuild version
                    version = parseFloat(msbuildVersions[msbuildVersions.length - 1]);
                }
            }
        }

        var specificVersion = versions[version];

        if (!specificVersion) {
            grunt.fatal('Unrecognised MSBuild version "' + version + '"');
        }

        if (version < 12) {
            var frameworkDir = 'Framework' + (processor === 64 ? processor : '');
            var buildExecutablePath = path.join(process.env.WINDIR, 'Microsoft.Net', frameworkDir, 'v' + specificVersion, 'MSBuild.exe');
        } else {
            var x64Dir = processor === 64 ? 'amd64' : '';
            var buildExecutablePath = path.join(programFiles, 'MSBuild', specificVersion, 'Bin', x64Dir, 'MSBuild.exe');
        }

        grunt.verbose.writeln('Using MSBuild at:' + buildExecutablePath.cyan);

        if (!fs.existsSync(buildExecutablePath)) {
            grunt.fatal('Unable to find MSBuild executable');
        }

        return path.normalize(buildExecutablePath);

    }

};
<|endoftext|>


<commit_before>/**
 * Bootstrap
 * src/api/core/bootstrap
 * Establishes a connection to the database, verifies it, and binds our db models.
 * Verifies application-wide configuration.
 */
import { Model } from 'objection';
import knex from '../services/postgres';
import Setting from '../routes/setting/setting.model';
import logger from './logger';

const startupMessage = `\n
  ------------------------------------------------------------ \n
                  🚀 Loaded BoldrAPI Configuration.
  ------------------------------------------------------------- \n
  `;

class bootstrap {
  static init() {
    this.initConfig();
    this.initDb();
    this.validateEnvVars();
  }

  static initConfig() {
    logger.info(startupMessage);
  }
  static validateEnvVars() {
    this.validateNodeEnv();
  }
  static validateNodeEnv() {
  // Check to see that the `process.env.NODE_ENV has been
  // set to an appropriate value of `development`, `production`
  // or `test`. If not, alert the user and default to `development`

    switch (process.env.NODE_ENV) {
      case 'development':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      case 'production':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      case 'test':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      default:
        logger.error('Error: process.env.NODE_ENV should be set to a valid '
        + ' value such as \'production\', \'development\', or \'test\'.');
        logger.info(`Value received: ${process.env.NODE_ENV}`);
        logger.info('Defaulting value for: development');
        process.env.NODE_ENV = 'development';
        break;
    }

    return;
  }
  static initDb() {
    logger.info('initDb: Binding to Knex instance and making a test query.');
    // bind Objection models to db instance.
    Model.knex(knex);
    Setting.query()
    .count('*')
    .catch((e) => {
      logger.error('Query failed', { error: e.message, stack: e.stack });
    });
  }
}

export default bootstrap;
<commit_msg>update readme<commit_after>/**
 * Bootstrap
 * src/api/core/bootstrap
 * Establishes a connection to the database, verifies it, and binds our db models.
 * Verifies application-wide configuration.
 */
import { Model } from 'objection';
import knex from '../services/postgres';
import Setting from '../routes/setting/setting.model';
import logger from './logger';

const startupMessage = `\n
  ------------------------------------------------------------ \n
                  🚀 Loaded BoldrAPI Configuration.
  ------------------------------------------------------------- \n
  `;

class bootstrap {
  static init() {
    this.initConfig();
    this.initDb();
    this.validateEnvVars();
  }

  static initConfig() {
    logger.info(startupMessage);
  }
  static validateEnvVars() {
    this.validateNodeEnv();
  }
  static validateNodeEnv() {
  // Check to see that the `process.env.NODE_ENV has been
  // set to an appropriate value of `development`, `production`
  // or `test`. If not, alert the user and default to `development`

    switch (process.env.NODE_ENV) {
      case 'development':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      case 'production':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      case 'test':
        logger.info(`✳  Node environment set for ${process.env.NODE_ENV}`);
        break;

      default:
        logger.error('Error: process.env.NODE_ENV should be set to a valid '
        + ' value such as \'production\', \'development\', or \'test\'.');
        logger.info(`Value received: ${process.env.NODE_ENV}`);
        logger.info('Defaulting value for: development');
        process.env.NODE_ENV = 'development';
        break;
    }

    return;
  }
  static initDb() {
    logger.info('initDb: Binding to Knex instance and making a test query.');
    // bind Objection models to db instance.
    Model.knex(knex);
  }
}

export default bootstrap;
<|endoftext|>


<commit_before>'use strict';
const r = require('../services/reddit');
let reportedItemNames = new Set();
let hasFinishedFirstRun = false;

const SUBREDDITS = ['pokemontrades', 'SVExchange'];

module.exports = {
  period: 60,
  onStart: true,
  task () {
    return r.get_subreddit(SUBREDDITS.join('+')).get_reports({limit: 25}).then(items => {
      // Don't output the new reports on the first fetch, as that would cause old reports to be listed.
      // Unfortunately, there is no way to tell whether reports on an item have been ignored using the OAuth API.
      const newItemsToReport = hasFinishedFirstRun ? items.filter(item => !reportedItemNames.has(item.name)) : [];
      items.forEach(item => reportedItemNames.add(item.name));
      hasFinishedFirstRun = true;
      return newItemsToReport.map(formatItem);
    });
  }
};

function formatItem (item) {
  const permalink = item.constructor.name === 'Comment' ? item.link_url + item.id : item.url;
  return `[NEW REPORTED ITEM] ${item.constructor.name} by /u/${item.author.name}: ${permalink}`;
}
<commit_msg>Made reports less aggressive-sounding<commit_after>'use strict';
const r = require('../services/reddit');
let reportedItemNames = new Set();
let hasFinishedFirstRun = false;

const SUBREDDITS = ['pokemontrades', 'SVExchange'];

module.exports = {
  period: 60,
  onStart: true,
  task () {
    return r.get_subreddit(SUBREDDITS.join('+')).get_reports({limit: 25}).then(items => {
      // Don't output the new reports on the first fetch, as that would cause old reports to be listed.
      // Unfortunately, there is no way to tell whether reports on an item have been ignored using the OAuth API.
      const newItemsToReport = hasFinishedFirstRun ? items.filter(item => !reportedItemNames.has(item.name)) : [];
      items.forEach(item => reportedItemNames.add(item.name));
      hasFinishedFirstRun = true;
      return newItemsToReport.map(formatItem);
    });
  }
};

function formatItem (item) {
  const permalink = item.constructor.name === 'Comment' ? item.link_url + item.id : item.url;
  return `[New report] ${item.constructor.name} by /u/${item.author.name}: ${permalink}`;
}
<|endoftext|>


<commit_before>/*
 * grunt-topcoat
 *
 */

'use strict';

var fs = require('fs'),
    path = require('path'),
    request = require('request'),
    ProgressBar = require('progress');

module.exports = function(grunt) {

    grunt.registerMultiTask('topcoat', 'Downloads specified repos for use in the TopDoat build process.', function() {
        var _ = grunt.util._,
            async = grunt.util.async,
            done = this.async(),
            file = grunt.file,
            options = this.options(),
            srcPath = options.srcPath || "src/",
            deps = options.repos,
            controls = deps.controls || {},
            skins = deps.skins || {},
            theme = deps.theme || {};

        // Splits the supplied user/repo name so we can use just the repo name
        //   for the zip file name.
        //   Example:
        //     topcoat/button
        //     button.zip
        var getDirectoryName = function(repo) {
                if (repo) {
                    return repo.split('/')[1];
                }
            };

        // If a version number is given we assume it is a tag and use this url
        // convention:
        // https://github.com/user/repo/archive/0.1.0.zip
        //
        // If no tag is given we use the download api with this url convention:
        // https://api.github.com/repos/user/repo/zipball/dev
        var getDownloadURL = function(repo, tag) {
                var downloadURL = '';
                if (tag) {
                    downloadURL = getTagArchiveURL(repo, tag);
                } else {
                    downloadURL = getNightlyArchiveURL(repo);
                }
                return downloadURL;
            };

        // Returns a download url for a tagged git archive
        // repo: user/repo unique name of git repo. Ex: topcoat/button
        // tag:  tag number of git tag to use
        // https://github.com/user/repo/archive/0.1.0.zip
        var getTagArchiveURL = function(repo, tag) {
                var prefix = "https://github.com/",
                    suffix = "/archive/",
                    ext = ".zip";

                return prefix + repo + suffix + tag + ext;
            };

        // Returns a download url for the current master of a git repo
        // repo: user/repo unique name of git repo. Ex: topcoat/button
        // https://api.github.com/repos/user/repo/zipball/dev
        // api is described here:
        // http://developer.github.com/v3/repos/contents/#get-archive-link
        var getNightlyArchiveURL = function(repo) {
                var prefix = "https://api.github.com/repos/",
                    suffix = "/zipball";

                return prefix + repo + suffix;
            };

        // Cross platform "curl" like functionality
        // url: url to download from
        // path: path to write the downloaded artifact to
        // callback: function to call once download completes or error is
        // thrown
        var curl = function(url, path, callback) {
                var req = request.get({
                    'url': url,
                    'encoding': 'binary'
                }, function(error, result, body) {
                    if (!error) {
                        fs.writeFileSync(path, body, 'binary');
                    } else {
                        grunt.fail.fatal(error);
                    }
                    callback(error, body);
                });

//                req.on('response', function(res) {
//                    var len = parseInt(res.headers['content-length'], 10);
//
//                    console.log();
//                    var bar = new ProgressBar('  downloading [:bar] :percent :etas', {
//                        complete: '=',
//                        incomplete: ' ',
//                        width: 20,
//                        total: len
//                    });
//
//                    res.on('data', function(chunk) {
//                        bar.tick(chunk.length);
//                    });
//
//                    res.on('end', function() {
//                        console.log('\n');
//                    });
//                });
            };

        // Loop over topcoat dependency object and downloads dependecies in
        // order.
        // obj: topcoat dependency object defined in package.json
        // path: destination directory path to download dependencies into
        // callback: function to call once all dependencies have finished
        // downloading
        var downloadResources = function(obj, path, callback) {
                var urls = [];
                _.forIn(obj, function(value, key) {
                    var name = getDirectoryName(key);
                    urls.push({
                        name: name,
                        url: getDownloadURL(key, value)
                    });
                });

                async.forEachSeries(urls, function(obj, next) {
                    var zipPath = path + obj.name + ".zip";
                    grunt.log.writeln("Downloading: " + obj.url + "\n into >> " + zipPath);
                    curl(obj.url, zipPath, next);
                }, callback);
            };

        // Download controls, theme and skins
        // controls and the theme to use is downloaded into the topcoat
        // repo by the topcoat grunt script
        //
        // skins are downloaded into the theme by the theme repos grunt
        // script
        // TODO: Find out a way to automate calling grunt on the theme
        // after it has been downloaded and unzipped in the topcoat repo
        async.series([

        function(callback) {
            // Download controls into srcPath/controls/
            if (!_.isEmpty(controls)) {
                var controlsPath = srcPath + "controls/";
                file.mkdir(controlsPath);
                downloadResources(controls, controlsPath, callback);
            } else {
                callback();
                grunt.log.writeln("No controls specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:controls');
            callback();
        },

        function(callback) {
            // Download theme into srcPath/theme
            if (!_.isEmpty(theme)) {
                downloadResources(theme, srcPath, callback);
            } else {
                callback();
                grunt.log.writeln("No theme specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:theme');
            callback();
        },

        function(callback) {
            // FIXME: Need to unzip the theme before we can download skins
            // into it.
            // Download skins into srcPath/theme-*/skins/
            if (!_.isEmpty(skins)) {
                var themePath = grunt.file.expand('src/theme-*'),
                    skinsPath = srcPath + "skins/";

                grunt.log.write("themePath "+ themePath);
                file.mkdir(skinsPath);
                downloadResources(skins, skinsPath, callback);
            } else {
                callback();
                grunt.log.writeln("No skins specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:skins');
            callback();
        },

        function(callback) {
            grunt.task.run('clean:zip');
            callback();
        },

        function() {
            done();
        }]);
    });
};
<commit_msg>Adding progress bar. Adding unzip and clean to task.<commit_after>/*
 * grunt-topcoat
 *
 */

'use strict';

var fs = require('fs'),
    path = require('path'),
    request = require('request'),
    ProgressBar = require('progress');

module.exports = function(grunt) {

    grunt.registerMultiTask('topcoat', 'Downloads specified repos for use in the TopDoat build process.', function() {
        var _ = grunt.util._,
            async = grunt.util.async,
            done = this.async(),
            file = grunt.file,
            options = this.options(),
            srcPath = options.srcPath || "src/",
            deps = options.repos,
            controls = deps.controls || {},
            skins = deps.skins || {},
            theme = deps.theme || {};

        // Splits the supplied user/repo name so we can use just the repo name
        //   for the zip file name.
        //   Example:
        //     topcoat/button
        //     button.zip
        var getDirectoryName = function(repo) {
                if (repo) {
                    return repo.split('/')[1];
                }
            };

        // If a version number is given we assume it is a tag and use this url
        // convention:
        // https://github.com/user/repo/archive/0.1.0.zip
        //
        // If no tag is given we use the download api with this url convention:
        // https://api.github.com/repos/user/repo/zipball/dev
        var getDownloadURL = function(repo, tag) {
                var downloadURL = '';
                if (tag) {
                    downloadURL = getTagArchiveURL(repo, tag);
                } else {
                    downloadURL = getNightlyArchiveURL(repo);
                }
                return downloadURL;
            };

        // Returns a download url for a tagged git archive
        // repo: user/repo unique name of git repo. Ex: topcoat/button
        // tag:  tag number of git tag to use
        // https://github.com/user/repo/archive/0.1.0.zip
        var getTagArchiveURL = function(repo, tag) {
                var prefix = "https://github.com/",
                    suffix = "/archive/",
                    ext = ".zip";

                return prefix + repo + suffix + tag + ext;
            };

        // Returns a download url for the current master of a git repo
        // repo: user/repo unique name of git repo. Ex: topcoat/button
        // https://api.github.com/repos/user/repo/zipball/dev
        // api is described here:
        // http://developer.github.com/v3/repos/contents/#get-archive-link
        var getNightlyArchiveURL = function(repo) {
                var prefix = "https://api.github.com/repos/",
                    suffix = "/zipball";

                return prefix + repo + suffix;
            };

        // Cross platform "curl" like functionality
        // url: url to download from
        // path: path to write the downloaded artifact to
        // callback: function to call once download completes or error is
        // thrown
        var curl = function(url, path, callback) {
                var req = request.get({
                    'url': url,
                    'encoding': 'binary'
                }, function(error, response, body) {
                    if (!error) {
                        fs.writeFileSync(path, body, 'binary');
                    } else {
                        grunt.fail.fatal(error);
                    }
                    callback(error, body);
                });

                req.on('response', function(res) {
                    var len = parseInt(res.headers['content-length'], 10);

                    var bar = new ProgressBar('Progress [:bar] :percent :etas', {
                        complete: '=',
                        incomplete: ' ',
                        width: 20,
                        total: len
                    });

                    res.on('data', function(chunk) {
                        bar.tick(chunk.length);
                    });
                });
            };

        // Loop over topcoat dependency object and downloads dependecies in
        // order.
        // obj: topcoat dependency object defined in package.json
        // path: destination directory path to download dependencies into
        // callback: function to call once all dependencies have finished
        // downloading
        var downloadResources = function(obj, path, callback) {
                var urls = [];
                _.forIn(obj, function(value, key) {
                    var name = getDirectoryName(key);
                    urls.push({
                        name: name,
                        url: getDownloadURL(key, value)
                    });
                });

                async.forEachSeries(urls, function(obj, next) {
                    var zipPath = path + obj.name + ".zip";
                    grunt.log.writeln("\nDownloading: " + obj.url + "\nTo => " + zipPath);
                    curl(obj.url, zipPath, next);
                }, callback);
            };

        // Download controls, theme and skins into specified folders for the
        // build
        async.series([

        function(callback) {
            // Download controls into srcPath/controls/
            if (!_.isEmpty(controls)) {
                var controlsPath = srcPath + "controls/";
                file.mkdir(controlsPath);
                downloadResources(controls, controlsPath, callback);
            } else {
                callback();
                grunt.log.writeln("No controls specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:controls');
            callback();
        },

        function(callback) {
            // Download theme into srcPath/theme
            if (!_.isEmpty(theme)) {
                downloadResources(theme, srcPath, callback);
            } else {
                callback();
                grunt.log.writeln("No theme specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:theme');
            callback();
        },

        function(callback) {
            // Download theme into srcPath/skins
            if (!_.isEmpty(skins)) {
                var skinsPath = srcPath + "skins/";
                file.mkdir(skinsPath);
                downloadResources(skins, skinsPath, callback);
            } else {
                callback();
                grunt.log.writeln("No skins specified");
            }
        },

        function(callback) {
            grunt.task.run('unzip:skins');
            callback();
        },

        function(callback) {
            grunt.task.run('clean:zip');
            callback();
        },

        function() {
            done();
        }]);
    });
};
<|endoftext|>


<commit_before>require('ember-handlebars/ext');

/**
@module ember
@submodule ember-handlebars
*/

/**
  `loc` looks up the string in the localized strings hash.
  This is a convenient way to localize text. For example:

  ```html
  <script type="text/x-handlebars" data-template-name="home">
    {{loc welcome}}
  </script>
  ```

  Take note that `welcome` is a string and not an object
  reference.

  @method loc
  @for Ember.Handlebars.helpers
  @param {String} str The string to format
*/

Ember.Handlebars.registerHelper('loc', function(str) {
  return Ember.String.loc(str);
});
<commit_msg>Improve example for {{loc}}<commit_after>require('ember-handlebars/ext');

/**
@module ember
@submodule ember-handlebars
*/

/**
  `loc` looks up the string in the localized strings hash.
  This is a convenient way to localize text. For example:

  ```javascript
  App.ApplicationController = Ember.Controller.extend({
    welcomeMessage: '_Hello World'
  });

  Ember.STRINGS = {
    '_Hello World': 'Bonjour le monde',
  };
  ```

  ```handlebars
  <span>{{loc welcomeMessage}}<span>
  ```

  ```html
  <span>Bonjour le monde</span>
  ```

  @method loc
  @for Ember.Handlebars.helpers
  @param {String} str The string to format
*/

Ember.Handlebars.registerHelper('loc', function(str) {
  return Ember.String.loc(str);
});
<|endoftext|>


<commit_before>module.exports = {
  'plugins': [
    'react'
  ],
  'parserOptions': {
    'ecmaFeatures': {
      'jsx': true,
    },
  },
  'ecmaFeatures': {
    'jsx': true
  },
  // View link below for react rules documentation
  // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules
  'rules': {
    // specify whether double or single quotes should be used in JSX attributes
    // http://eslint.org/docs/rules/jsx-quotes
    'jsx-quotes': [2, 'prefer-double'],
    // Prevent missing displayName in a React component definition
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
    'react/display-name': [0, { 'ignoreTranspilerName': false }],
    // Forbid certain propTypes (any, array, object)
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md
    'react/forbid-prop-types': [0, { 'forbid': ['any', 'array', 'object'] }],
    // Enforce boolean attributes notation in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
    'react/jsx-boolean-value': [2, 'never'],
    // Validate closing bracket location in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md
    'react/jsx-closing-bracket-location': [2, 'line-aligned'],
    // Enforce or disallow spaces inside of curly braces in JSX attributes
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md
    'react/jsx-curly-spacing': [2, 'never', { 'allowMultiline': true }],
    // Enforce event handler naming conventions in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md
    'react/jsx-handler-names': [0, {
      'eventHandlerPrefix': 'handle',
      'eventHandlerPropPrefix': 'on',
    }],
    // Validate props indentation in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
    'react/jsx-indent-props': [2, 2],
    // Validate JSX has key prop when in array or iterator
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
    'react/jsx-key': 0,
    // Limit maximum of props on a single line in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md
    'react/jsx-max-props-per-line': [0, { 'maximum': 1 }],
    // Prevent usage of .bind() in JSX props
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
    'react/jsx-no-bind': [2, {
      'ignoreRefs': true,
      'allowArrowFunctions': true,
      'allowBind': false,
    }],
    // Prevent duplicate props in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md
    'react/jsx-no-duplicate-props': [0, { 'ignoreCase': false }],
    // Prevent usage of unwrapped JSX strings
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md
    'react/jsx-no-literals': 0,
    // Disallow undeclared variables in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md
    'react/jsx-no-undef': 2,
    // Enforce PascalCase for user-defined JSX components
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
    'react/jsx-pascal-case': 2,
    // Enforce propTypes declarations alphabetical sorting
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md
    'react/sort-prop-types': [0, {
      'ignoreCase': false,
      'callbacksLast': false,
    }],
    // deprecated in favor of react/jsx-sort-props
    'react/jsx-sort-prop-types': 0,
    // Enforce props alphabetical sorting
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md
    'react/jsx-sort-props': [0, {
      'ignoreCase': false,
      'callbacksLast': false,
    }],
    // Prevent React to be incorrectly marked as unused
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md
    'react/jsx-uses-react': [2, { 'pragma': 'React' }],
    // Prevent variables used in JSX to be incorrectly marked as unused
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md
    'react/jsx-uses-vars': 2,
    // Prevent usage of dangerous JSX properties
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md
    'react/no-danger': 0,
    // Prevent usage of deprecated methods
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md
    'react/no-deprecated': [1, { 'react': '0.14.0' }],
    // Prevent usage of setState in componentDidMount
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md
    'react/no-did-mount-set-state': [2, 'allow-in-func'],
    // Prevent usage of setState in componentDidUpdate
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md
    'react/no-did-update-set-state': [2, 'allow-in-func'],
    // Prevent direct mutation of this.state
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
    'react/no-direct-mutation-state': 0,
    // Prevent usage of isMounted
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
    'react/no-is-mounted': 2,
    // Prevent multiple component definition per file
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
    'react/no-multi-comp': [2, { 'ignoreStateless': true }],
    // Prevent usage of setState
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md
    'react/no-set-state': 0,
    // Prevent using string references
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md
    'react/no-string-refs': 0,
    // Prevent usage of unknown DOM property
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md
    'react/no-unknown-property': 2,
    // Require ES6 class declarations over React.createClass
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
    'react/prefer-es6-class': [2, 'always'],
    // Require stateless functions when not using lifecycle methods, setState or ref
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
    'react/prefer-stateless-function': 2,
    // Prevent missing props validation in a React component definition
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
    'react/prop-types': [2, { 'ignore': [], 'customValidators': [] }],
    // Prevent missing React when using JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md
    'react/react-in-jsx-scope': 2,
    // Restrict file extensions that may be required
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-extension.md
    'react/require-extension': [0, { 'extensions': ['.jsx'] }],
    // Require render() methods to return something
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md
    'react/require-render-return': 2,
    // Prevent extra closing tags for components without children
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md
    'react/self-closing-comp': 2,
    // Enforce spaces before the closing bracket of self-closing JSX elements
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md
    'react/jsx-space-before-closing': [2, 'always'],
    // Enforce component methods order
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md
    'react/sort-comp': [2, {
      'order': [
        'static-methods',
        'lifecycle',
        '/^on.+$/',
        '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
        'everything-else',
        '/^render.+$/',
        'render'
      ],
    }],
    // Prevent missing parentheses around multilines JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md
    'react/wrap-multilines': [2, {
      'declaration': true,
      'assignment': true,
      'return': true
    }],
    // Require that the first prop in a JSX element be on a new line when the element is multiline
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
    'react/jsx-first-prop-new-line': [2, 'multiline'],
    // enforce spacing around jsx equals signs
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md
    'react/jsx-equals-spacing': [2, 'never'],
    // enforce JSX indentation
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
    'react/jsx-indent': [2, 2],
    // disallow target="_blank" on links
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
    // TODO: enable
    'react/jsx-no-target-blank': 0
  },
  'settings': {
    'import/resolver': {
      'node': {
        'extensions': ['.js', '.jsx', '.json']
      }
    },
    'react': {
      'pragma': 'React',
      'version': '0.14'
    },
  }
};
<commit_msg>[eslint config] [react] [patch] loosen `jsx-pascal-case` rule to allow all caps component names<commit_after>module.exports = {
  'plugins': [
    'react'
  ],
  'parserOptions': {
    'ecmaFeatures': {
      'jsx': true,
    },
  },
  'ecmaFeatures': {
    'jsx': true
  },
  // View link below for react rules documentation
  // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules
  'rules': {
    // specify whether double or single quotes should be used in JSX attributes
    // http://eslint.org/docs/rules/jsx-quotes
    'jsx-quotes': [2, 'prefer-double'],
    // Prevent missing displayName in a React component definition
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
    'react/display-name': [0, { 'ignoreTranspilerName': false }],
    // Forbid certain propTypes (any, array, object)
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md
    'react/forbid-prop-types': [0, { 'forbid': ['any', 'array', 'object'] }],
    // Enforce boolean attributes notation in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
    'react/jsx-boolean-value': [2, 'never'],
    // Validate closing bracket location in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md
    'react/jsx-closing-bracket-location': [2, 'line-aligned'],
    // Enforce or disallow spaces inside of curly braces in JSX attributes
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md
    'react/jsx-curly-spacing': [2, 'never', { 'allowMultiline': true }],
    // Enforce event handler naming conventions in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md
    'react/jsx-handler-names': [0, {
      'eventHandlerPrefix': 'handle',
      'eventHandlerPropPrefix': 'on',
    }],
    // Validate props indentation in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
    'react/jsx-indent-props': [2, 2],
    // Validate JSX has key prop when in array or iterator
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
    'react/jsx-key': 0,
    // Limit maximum of props on a single line in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md
    'react/jsx-max-props-per-line': [0, { 'maximum': 1 }],
    // Prevent usage of .bind() in JSX props
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
    'react/jsx-no-bind': [2, {
      'ignoreRefs': true,
      'allowArrowFunctions': true,
      'allowBind': false,
    }],
    // Prevent duplicate props in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md
    'react/jsx-no-duplicate-props': [0, { 'ignoreCase': false }],
    // Prevent usage of unwrapped JSX strings
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md
    'react/jsx-no-literals': 0,
    // Disallow undeclared variables in JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md
    'react/jsx-no-undef': 2,
    // Enforce PascalCase for user-defined JSX components
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
    'react/jsx-pascal-case': [2, {
      'allowAllCaps': true,
      'ignore': [],
    }],
    // Enforce propTypes declarations alphabetical sorting
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md
    'react/sort-prop-types': [0, {
      'ignoreCase': false,
      'callbacksLast': false,
    }],
    // deprecated in favor of react/jsx-sort-props
    'react/jsx-sort-prop-types': 0,
    // Enforce props alphabetical sorting
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md
    'react/jsx-sort-props': [0, {
      'ignoreCase': false,
      'callbacksLast': false,
    }],
    // Prevent React to be incorrectly marked as unused
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md
    'react/jsx-uses-react': [2, { 'pragma': 'React' }],
    // Prevent variables used in JSX to be incorrectly marked as unused
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md
    'react/jsx-uses-vars': 2,
    // Prevent usage of dangerous JSX properties
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md
    'react/no-danger': 0,
    // Prevent usage of deprecated methods
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md
    'react/no-deprecated': [1, { 'react': '0.14.0' }],
    // Prevent usage of setState in componentDidMount
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md
    'react/no-did-mount-set-state': [2, 'allow-in-func'],
    // Prevent usage of setState in componentDidUpdate
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md
    'react/no-did-update-set-state': [2, 'allow-in-func'],
    // Prevent direct mutation of this.state
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
    'react/no-direct-mutation-state': 0,
    // Prevent usage of isMounted
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
    'react/no-is-mounted': 2,
    // Prevent multiple component definition per file
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
    'react/no-multi-comp': [2, { 'ignoreStateless': true }],
    // Prevent usage of setState
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md
    'react/no-set-state': 0,
    // Prevent using string references
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md
    'react/no-string-refs': 0,
    // Prevent usage of unknown DOM property
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md
    'react/no-unknown-property': 2,
    // Require ES6 class declarations over React.createClass
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
    'react/prefer-es6-class': [2, 'always'],
    // Require stateless functions when not using lifecycle methods, setState or ref
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
    'react/prefer-stateless-function': 2,
    // Prevent missing props validation in a React component definition
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
    'react/prop-types': [2, { 'ignore': [], 'customValidators': [] }],
    // Prevent missing React when using JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md
    'react/react-in-jsx-scope': 2,
    // Restrict file extensions that may be required
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-extension.md
    'react/require-extension': [0, { 'extensions': ['.jsx'] }],
    // Require render() methods to return something
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md
    'react/require-render-return': 2,
    // Prevent extra closing tags for components without children
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md
    'react/self-closing-comp': 2,
    // Enforce spaces before the closing bracket of self-closing JSX elements
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md
    'react/jsx-space-before-closing': [2, 'always'],
    // Enforce component methods order
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md
    'react/sort-comp': [2, {
      'order': [
        'static-methods',
        'lifecycle',
        '/^on.+$/',
        '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
        'everything-else',
        '/^render.+$/',
        'render'
      ],
    }],
    // Prevent missing parentheses around multilines JSX
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md
    'react/wrap-multilines': [2, {
      'declaration': true,
      'assignment': true,
      'return': true
    }],
    // Require that the first prop in a JSX element be on a new line when the element is multiline
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
    'react/jsx-first-prop-new-line': [2, 'multiline'],
    // enforce spacing around jsx equals signs
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md
    'react/jsx-equals-spacing': [2, 'never'],
    // enforce JSX indentation
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
    'react/jsx-indent': [2, 2],
    // disallow target="_blank" on links
    // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
    // TODO: enable
    'react/jsx-no-target-blank': 0
  },
  'settings': {
    'import/resolver': {
      'node': {
        'extensions': ['.js', '.jsx', '.json']
      }
    },
    'react': {
      'pragma': 'React',
      'version': '0.14'
    },
  }
};
<|endoftext|>


<commit_before>/**
 * app.js
 *
 * Use `app.js` to run your app without `sails lift`.
 * To start the server, run: `node app.js`.
 *
 * This is handy in situations where the sails CLI is not relevant or useful.
 *
 * For example:
 *   => `node app.js`
 *   => `forever start app.js`
 *   => `node debug app.js`
 *   => `modulus deploy`
 *   => `heroku scale`
 *
 *
 * The same command-line arguments are supported, e.g.:
 * `node app.js --silent --port=80 --prod`
 */

// Ensure a "sails" can be located:
(function() {
  var sails;
  try {
    sails = require('sails');
  } catch (e) {
    console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.');
    console.error('To do that, run `npm install sails`');
    console.error('');
    console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.');
    console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,');
    console.error('but if it doesn\'t, the app will run with the global sails instead!');
    return;
  }

  // Try to get `rc` dependency
  var rc;
  try {
    rc = require('rc');
  } catch (e0) {
    try {
      rc = require('sails/node_modules/rc');
    } catch (e1) {
      console.error('Could not find dependency: `rc`.');
      console.error('Your `.sailsrc` file(s) will be ignored.');
      console.error('To resolve this, run:');
      console.error('npm install rc --save');
      rc = function () { return {}; };
    }
  }

  // Start server
  sails.lift(rc('sails'));
})();
<commit_msg>Ensure app always lifts in its own root directory Fixes issues with `forever start /path/to/app.js` resulting in a bunch of "not found" responses, among other things.<commit_after>/**
 * app.js
 *
 * Use `app.js` to run your app without `sails lift`.
 * To start the server, run: `node app.js`.
 *
 * This is handy in situations where the sails CLI is not relevant or useful.
 *
 * For example:
 *   => `node app.js`
 *   => `forever start app.js`
 *   => `node debug app.js`
 *   => `modulus deploy`
 *   => `heroku scale`
 *
 *
 * The same command-line arguments are supported, e.g.:
 * `node app.js --silent --port=80 --prod`
 */

// Ensure we're in the project directory, so relative paths work as expected
// no matter where we actually lift from.
process.chdir(__dirname);

// Ensure a "sails" can be located:
(function() {
  var sails;
  try {
    sails = require('sails');
  } catch (e) {
    console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.');
    console.error('To do that, run `npm install sails`');
    console.error('');
    console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.');
    console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,');
    console.error('but if it doesn\'t, the app will run with the global sails instead!');
    return;
  }

  // Try to get `rc` dependency
  var rc;
  try {
    rc = require('rc');
  } catch (e0) {
    try {
      rc = require('sails/node_modules/rc');
    } catch (e1) {
      console.error('Could not find dependency: `rc`.');
      console.error('Your `.sailsrc` file(s) will be ignored.');
      console.error('To resolve this, run:');
      console.error('npm install rc --save');
      rc = function () { return {}; };
    }
  }

  // Start server
  sails.lift(rc('sails'));
})();
<|endoftext|>


<commit_before>module.exports = {
  'rules': {
    // enforce spacing inside array brackets
    'array-bracket-spacing': [2, 'never'],
    // enforce one true brace style
    'brace-style': [2, '1tbs', {'allowSingleLine': true }],
    // require camel case names
    'camelcase': [2, {'properties': 'never'}],
    // enforce spacing before and after comma
    'comma-spacing': [2, {'before': false, 'after': true}],
    // enforce one true comma style
    'comma-style': [2, 'last'],
    // disallow padding inside computed properties
    'computed-property-spacing': [2, 'never'],
    // enforces consistent naming when capturing the current execution context
    'consistent-this': 0,
    // enforce newline at the end of file, with no multiple empty lines
    'eol-last': 2,
    // require function expressions to have a name
    'func-names': 1,
    // enforces use of function declarations or expressions
    'func-style': 0,
    // this option enforces minimum and maximum identifier lengths (variable names, property names etc.)
    'id-length': 0,
    // this option sets a specific tab width for your code
    // https://github.com/eslint/eslint/blob/master/docs/rules/indent.md
    'indent': [2, 2, { "SwitchCase": 1, "VariableDeclarator": 1 }],
    // specify whether double or single quotes should be used in JSX attributes
    // http://eslint.org/docs/rules/jsx-quotes
    'jsx-quotes': [2, 'prefer-double'],
    // enforces spacing between keys and values in object literal properties
    'key-spacing': [2, {'beforeColon': false, 'afterColon': true}],
    // enforces empty lines around comments
    'lines-around-comment': 0,
    // disallow mixed 'LF' and 'CRLF' as linebreaks
    'linebreak-style': 0,
    // specify the maximum length of a line in your program
    // https://github.com/eslint/eslint/blob/master/docs/rules/max-len.md
    'max-len': [2, 100, 2, {
      'ignoreUrls': false,
      'ignoreComments': false
    }],
    // specify the maximum depth callbacks can be nested
    'max-nested-callbacks': 0,
    // require a capital letter for constructors
    'new-cap': [2, {'newIsCap': true}],
    // disallow the omission of parentheses when invoking a constructor with no arguments
    'new-parens': 0,
    // allow/disallow an empty newline after var statement
    'newline-after-var': 0,
    // disallow use of the Array constructor
    'no-array-constructor': 0,
    // disallow use of the continue statement
    'no-continue': 0,
    // disallow comments inline after code
    'no-inline-comments': 0,
    // disallow if as the only statement in an else block
    'no-lonely-if': 0,
    // disallow mixed spaces and tabs for indentation
    'no-mixed-spaces-and-tabs': 2,
    // disallow multiple empty lines and only one newline at the end
    'no-multiple-empty-lines': [2, {'max': 2, 'maxEOF': 1}],
    // disallow nested ternary expressions
    'no-nested-ternary': 2,
    // disallow use of the Object constructor
    'no-new-object': 2,
    // disallow space between function identifier and application
    'no-spaced-func': 2,
    // disallow the use of ternary operators
    'no-ternary': 0,
    // disallow trailing whitespace at the end of lines
    'no-trailing-spaces': 2,
    // disallow dangling underscores in identifiers
    'no-underscore-dangle': 0,
    // disallow the use of Boolean literals in conditional expressions
    'no-unneeded-ternary': 0,
    // require padding inside curly braces
    'object-curly-spacing': [2, 'always'],
    // allow just one var statement per function
    'one-var': [2, 'never'],
    // require assignment operator shorthand where possible or prohibit it entirely
    'operator-assignment': 0,
    // enforce operators to be placed before or after line breaks
    'operator-linebreak': 0,
    // enforce padding within blocks
    'padded-blocks': [2, 'never'],
    // require quotes around object literal property names
    // http://eslint.org/docs/rules/quote-props.html
    'quote-props': [2, 'as-needed', { 'keywords': true, 'unnecessary': true, 'numbers': false }],
    // specify whether double or single quotes should be used
    'quotes': [2, 'single', 'avoid-escape'],
    // require identifiers to match the provided regular expression
    'id-match': 0,
    // enforce spacing before and after semicolons
    'semi-spacing': [2, {'before': false, 'after': true}],
    // require or disallow use of semicolons instead of ASI
    'semi': [2, 'always'],
    // sort variables within the same declaration block
    'sort-vars': 0,
    // require a space before certain keywords
    'space-before-keywords': [2, 'always'],
    // require a space after certain keywords
    'space-after-keywords': [2, 'always'],
    // require or disallow space before blocks
    'space-before-blocks': 2,
    // require or disallow space before function opening parenthesis
    // https://github.com/eslint/eslint/blob/master/docs/rules/space-before-function-paren.md
    'space-before-function-paren': [2, { 'anonymous': 'always', 'named': 'never' }],
    // require or disallow spaces inside parentheses
    'space-in-parens': [2, 'never'],
    // require spaces around operators
    'space-infix-ops': 2,
    // require a space after return, throw, and case
    'space-return-throw-case': 2,
    // Require or disallow spaces before/after unary operators
    'space-unary-ops': 0,
    // require or disallow a space immediately following the // or /* in a comment
    'spaced-comment': [2, 'always', {
      'exceptions': ['-', '+'],
      'markers': ['=', '!']           // space here to support sprockets directives
    }],
    // require regex literals to be wrapped in parentheses
    'wrap-regex': 0
  }
};
<commit_msg>[eslint config] [fix] because we use babel, keywords should not be quoted.<commit_after>module.exports = {
  'rules': {
    // enforce spacing inside array brackets
    'array-bracket-spacing': [2, 'never'],
    // enforce one true brace style
    'brace-style': [2, '1tbs', {'allowSingleLine': true }],
    // require camel case names
    'camelcase': [2, {'properties': 'never'}],
    // enforce spacing before and after comma
    'comma-spacing': [2, {'before': false, 'after': true}],
    // enforce one true comma style
    'comma-style': [2, 'last'],
    // disallow padding inside computed properties
    'computed-property-spacing': [2, 'never'],
    // enforces consistent naming when capturing the current execution context
    'consistent-this': 0,
    // enforce newline at the end of file, with no multiple empty lines
    'eol-last': 2,
    // require function expressions to have a name
    'func-names': 1,
    // enforces use of function declarations or expressions
    'func-style': 0,
    // this option enforces minimum and maximum identifier lengths (variable names, property names etc.)
    'id-length': 0,
    // this option sets a specific tab width for your code
    // https://github.com/eslint/eslint/blob/master/docs/rules/indent.md
    'indent': [2, 2, { "SwitchCase": 1, "VariableDeclarator": 1 }],
    // specify whether double or single quotes should be used in JSX attributes
    // http://eslint.org/docs/rules/jsx-quotes
    'jsx-quotes': [2, 'prefer-double'],
    // enforces spacing between keys and values in object literal properties
    'key-spacing': [2, {'beforeColon': false, 'afterColon': true}],
    // enforces empty lines around comments
    'lines-around-comment': 0,
    // disallow mixed 'LF' and 'CRLF' as linebreaks
    'linebreak-style': 0,
    // specify the maximum length of a line in your program
    // https://github.com/eslint/eslint/blob/master/docs/rules/max-len.md
    'max-len': [2, 100, 2, {
      'ignoreUrls': false,
      'ignoreComments': false
    }],
    // specify the maximum depth callbacks can be nested
    'max-nested-callbacks': 0,
    // require a capital letter for constructors
    'new-cap': [2, {'newIsCap': true}],
    // disallow the omission of parentheses when invoking a constructor with no arguments
    'new-parens': 0,
    // allow/disallow an empty newline after var statement
    'newline-after-var': 0,
    // disallow use of the Array constructor
    'no-array-constructor': 0,
    // disallow use of the continue statement
    'no-continue': 0,
    // disallow comments inline after code
    'no-inline-comments': 0,
    // disallow if as the only statement in an else block
    'no-lonely-if': 0,
    // disallow mixed spaces and tabs for indentation
    'no-mixed-spaces-and-tabs': 2,
    // disallow multiple empty lines and only one newline at the end
    'no-multiple-empty-lines': [2, {'max': 2, 'maxEOF': 1}],
    // disallow nested ternary expressions
    'no-nested-ternary': 2,
    // disallow use of the Object constructor
    'no-new-object': 2,
    // disallow space between function identifier and application
    'no-spaced-func': 2,
    // disallow the use of ternary operators
    'no-ternary': 0,
    // disallow trailing whitespace at the end of lines
    'no-trailing-spaces': 2,
    // disallow dangling underscores in identifiers
    'no-underscore-dangle': 0,
    // disallow the use of Boolean literals in conditional expressions
    'no-unneeded-ternary': 0,
    // require padding inside curly braces
    'object-curly-spacing': [2, 'always'],
    // allow just one var statement per function
    'one-var': [2, 'never'],
    // require assignment operator shorthand where possible or prohibit it entirely
    'operator-assignment': 0,
    // enforce operators to be placed before or after line breaks
    'operator-linebreak': 0,
    // enforce padding within blocks
    'padded-blocks': [2, 'never'],
    // require quotes around object literal property names
    // http://eslint.org/docs/rules/quote-props.html
    'quote-props': [2, 'as-needed', { 'keywords': false, 'unnecessary': true, 'numbers': false }],
    // specify whether double or single quotes should be used
    'quotes': [2, 'single', 'avoid-escape'],
    // require identifiers to match the provided regular expression
    'id-match': 0,
    // enforce spacing before and after semicolons
    'semi-spacing': [2, {'before': false, 'after': true}],
    // require or disallow use of semicolons instead of ASI
    'semi': [2, 'always'],
    // sort variables within the same declaration block
    'sort-vars': 0,
    // require a space before certain keywords
    'space-before-keywords': [2, 'always'],
    // require a space after certain keywords
    'space-after-keywords': [2, 'always'],
    // require or disallow space before blocks
    'space-before-blocks': 2,
    // require or disallow space before function opening parenthesis
    // https://github.com/eslint/eslint/blob/master/docs/rules/space-before-function-paren.md
    'space-before-function-paren': [2, { 'anonymous': 'always', 'named': 'never' }],
    // require or disallow spaces inside parentheses
    'space-in-parens': [2, 'never'],
    // require spaces around operators
    'space-infix-ops': 2,
    // require a space after return, throw, and case
    'space-return-throw-case': 2,
    // Require or disallow spaces before/after unary operators
    'space-unary-ops': 0,
    // require or disallow a space immediately following the // or /* in a comment
    'spaced-comment': [2, 'always', {
      'exceptions': ['-', '+'],
      'markers': ['=', '!']           // space here to support sprockets directives
    }],
    // require regex literals to be wrapped in parentheses
    'wrap-regex': 0
  }
};
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')

/**
 * Checks if the source is a directory.
 * @param {string} source
 */
function isDirectory(source) {
  return fs.lstatSync(source).isDirectory()
}

/**
 * Checks if the source is a directory.
 * @param {string} source
 */
function isSymlink(source) {
  return fs.lstatSync(source).isSymbolicLink()
}

/**
 * Gets the possible URLs from a directory.
 * @param {string} urlprefix
 * @param {string} directory
 */
function getUrlFromPagesDirectory(urlPrefix, directory) {
  return parseUrlForPages(urlPrefix, directory).map(
    // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
    (url) => new RegExp(`^${normalizeURL(url)}$`)
  )
}

/**
 * Recursively parse directory for page URLs.
 * @param {string} urlprefix
 * @param {string} directory
 */
function parseUrlForPages(urlprefix, directory) {
  const files = fs.readdirSync(directory)
  const res = []
  files.forEach((fname) => {
    if (/(\.(j|t)sx?)$/.test(fname)) {
      fname = fname.replace(/\[.*\]/g, '.*')
      if (/^index(\.(j|t)sx?)$/.test(fname)) {
        res.push(`${urlprefix}${fname.replace(/^index(\.(j|t)sx?)$/, '')}`)
      }
      res.push(`${urlprefix}${fname.replace(/(\.(j|t)sx?)$/, '')}`)
    } else {
      const dirPath = path.join(directory, fname)
      if (isDirectory(dirPath) && !isSymlink(dirPath)) {
        res.push(...parseUrlForPages(urlprefix + fname + '/', dirPath))
      }
    }
  })
  return res
}

/**
 * Takes a url and does the following things.
 *  - replace `index.html` with `/`
 *  - Makes sure all URLs are have a trainiling `/`
 *  - Removes query string
 * @param {string} url
 */
function normalizeURL(url) {
  if (!url) {
    return
  }
  url = url.split('?')[0]
  url = url.split('#')[0]
  url = url = url.replace(/(\/index\.html)$/, '/')
  // empty URLs should not be trailed with `/`, e.g. `#heading`
  if (url === '') {
    return url
  }
  url = url.endsWith('/') ? url : url + '/'
  return url
}

module.exports = {
  getUrlFromPagesDirectory,
  normalizeURL,
}
<commit_msg>fix typo in `eslint-plugin-next` code comments (#15583)<commit_after>const fs = require('fs')
const path = require('path')

/**
 * Checks if the source is a directory.
 * @param {string} source
 */
function isDirectory(source) {
  return fs.lstatSync(source).isDirectory()
}

/**
 * Checks if the source is a directory.
 * @param {string} source
 */
function isSymlink(source) {
  return fs.lstatSync(source).isSymbolicLink()
}

/**
 * Gets the possible URLs from a directory.
 * @param {string} urlprefix
 * @param {string} directory
 */
function getUrlFromPagesDirectory(urlPrefix, directory) {
  return parseUrlForPages(urlPrefix, directory).map(
    // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
    (url) => new RegExp(`^${normalizeURL(url)}$`)
  )
}

/**
 * Recursively parse directory for page URLs.
 * @param {string} urlprefix
 * @param {string} directory
 */
function parseUrlForPages(urlprefix, directory) {
  const files = fs.readdirSync(directory)
  const res = []
  files.forEach((fname) => {
    if (/(\.(j|t)sx?)$/.test(fname)) {
      fname = fname.replace(/\[.*\]/g, '.*')
      if (/^index(\.(j|t)sx?)$/.test(fname)) {
        res.push(`${urlprefix}${fname.replace(/^index(\.(j|t)sx?)$/, '')}`)
      }
      res.push(`${urlprefix}${fname.replace(/(\.(j|t)sx?)$/, '')}`)
    } else {
      const dirPath = path.join(directory, fname)
      if (isDirectory(dirPath) && !isSymlink(dirPath)) {
        res.push(...parseUrlForPages(urlprefix + fname + '/', dirPath))
      }
    }
  })
  return res
}

/**
 * Takes a URL and does the following things.
 *  - Replaces `index.html` with `/`
 *  - Makes sure all URLs are have a trailing `/`
 *  - Removes query string
 * @param {string} url
 */
function normalizeURL(url) {
  if (!url) {
    return
  }
  url = url.split('?')[0]
  url = url.split('#')[0]
  url = url = url.replace(/(\/index\.html)$/, '/')
  // Empty URLs should not be trailed with `/`, e.g. `#heading`
  if (url === '') {
    return url
  }
  url = url.endsWith('/') ? url : url + '/'
  return url
}

module.exports = {
  getUrlFromPagesDirectory,
  normalizeURL,
}
<|endoftext|>