<commit_before>/**
 * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the
 * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.
 */
var _ = require('lodash'),
    expect = require('expect.js'),
    parseIgnore = require('parse-gitignore');

/* global describe, it */
describe('project repository', function () {
    var fs = require('fs');

    describe('package.json', function () {
        var content,
            json;

        try {
            content = fs.readFileSync('./package.json').toString();
            json = JSON.parse(content);
        }
        catch (e) {
            console.error(e);
            content = '';
            json = {};
        }

        it('must have readable JSON content', function () {
            expect(content).to.be.ok();
            expect(json).to.not.eql({});
        });

        describe('package.json JSON data', function () {
            it('must have valid name, description and author', function () {
                expect(json).to.have.property('name', 'newman');
                expect(json).to.have.property('description', 'Command-line companion utility for Postman');
                expect(json).to.have.property('author', 'Postman Labs <help@getpostman.com> (=)');
                expect(json).to.have.property('license', 'Apache-2.0');
                expect(json).to.have.property('homepage', 'https://github.com/postmanlabs/newman');
                expect(json).to.have.property('bugs', 'https://github.com/postmanlabs/newman/issues');

                expect(json).to.have.property('repository');
                expect(json.repository).to.eql({
                    type: 'git',
                    url: 'git://github.com/postmanlabs/newman.git'
                });

                expect(json).to.have.property('keywords');
                expect(json.keywords).to.eql(['newman', 'postman', 'api', 'testing', 'ci', 'rest-client', 'rest']);

                expect(json).to.have.property('engines');
                expect(json.engines).to.eql({ node: '>=4' });
            });

            it('must have a valid version string in form of <major>.<minor>.<revision>', function () {
                // eslint-disable-next-line max-len
                expect(json.version).to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/);
            });
        });

        describe('binary definitions', function () {
            it('must exist', function () {
                expect(json.bin).be.ok();
                expect(json.bin).to.eql({ 'newman': './bin/newman.js' });
            });

            it('must have valid node shebang', function () {
                json.bin && Object.keys(json.bin).forEach(function (scriptName) {
                    var fileContent = fs.readFileSync(json.bin[scriptName]).toString();
                    expect(/^#!\/(bin\/bash|usr\/bin\/env\snode)[\r\n][\W\w]*$/g.test(fileContent)).to.be.ok();
                });
            });
        });

        describe('script definitions', function () {
            it('files must exist', function () {
                var scriptRegexJS = /^node\snpm\/.+\.js$/,
                    scriptRegexSH = /^\.\/npm\/.+\.sh$/;
                expect(json.scripts).to.be.ok();
                json.scripts && Object.keys(json.scripts).forEach(function (scriptName) {
                    expect(scriptRegexJS.test(json.scripts[scriptName]) ||
                        scriptRegexSH.test(json.scripts[scriptName])).to.be.ok();
                    expect(fs.existsSync('npm/' + scriptName + '.js') ||
                        fs.existsSync('npm/' + scriptName + '.sh')).to.be.ok();
                });
            });

            it('must have the hashbang defined', function () {
                json.scripts && Object.keys(json.scripts).forEach(function (scriptName) {
                    fs.readFile('npm/' + scriptName + '.js', function (err, fileContent) {
                        if (err) {
                            fileContent = fs.readFileSync('npm/' + scriptName + '.sh');
                        }
                        fileContent = fileContent.toString();
                        expect(/^#!\/(bin\/bash|usr\/bin\/env\snode)[\r\n][\W\w]*$/g.test(fileContent)).to.be.ok();
                    });
                });
            });
        });

        describe('dependencies', function () {
            it('must exist', function () {
                expect(json.dependencies).to.be.a('object');
            });

            it('must point to a valid and precise (no * or ^) semver', function () {
                json.dependencies && Object.keys(json.dependencies).forEach(function (item) {
                    expect(json.dependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });
        });

        describe('devDependencies', function () {
            it('must exist', function () {
                expect(json.devDependencies).to.be.a('object');
            });

            it('must point to a valid and precise (no * or ^) semver', function () {
                json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
                    expect(json.devDependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });

            it('should not overlap devDependencies', function () {
                var clean = [];

                json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
                    !json.dependencies[item] && clean.push(item);
                });

                expect(Object.keys(json.devDependencies)).to.eql(clean);
            });
        });

        describe('main entry script', function () {
            it('must point to a valid file', function (done) {
                expect(json.main).to.equal('index.js');
                fs.stat(json.main, done);
            });
        });
    });

    describe('README.md', function () {
        it('must exist', function (done) {
            fs.stat('./README.md', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./README.md').toString()).to.be.ok();
        });
    });

    describe('LICENSE.md', function () {
        it('must exist', function (done) {
            fs.stat('./LICENSE.md', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok();
        });
    });

    describe('.ignore files', function () {
        var gitignorePath = '.gitignore',
            npmignorePath = '.npmignore',
            npmignore = parseIgnore(npmignorePath),
            gitignore = parseIgnore(gitignorePath);

        describe(gitignorePath, function () {
            it('must exist', function (done) {
                fs.stat(gitignorePath, done);
            });

            it('must have valid content', function () {
                expect(_.isEmpty(gitignore)).to.not.be.ok();
            });
        });

        describe(npmignorePath, function () {
            it('must exist', function (done) {
                fs.stat(npmignorePath, done);
            });

            it('must have valid content', function () {
                expect(_.isEmpty(npmignore)).to.not.be.ok();
            });
        });

        it('.gitignore coverage must be a subset of .npmignore coverage', function () {
            expect(_.intersection(gitignore, npmignore)).to.eql(gitignore);
        });
    });

    describe('.eslintrc', function () {
        it('must exist', function (done) {
            fs.stat('./.eslintrc', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./.eslintrc').toString()).to.be.ok();
        });
    });

    describe('.nsprc', function () {
        it('must exist', function (done) {
            fs.stat('./.nsprc', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./.nsprc').toString()).to.be.ok();
        });
    });
});
<commit_msg>Made the code in system tests a little cleaner<commit_after>/**
 * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the
 * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.
 */
var _ = require('lodash'),
    expect = require('expect.js'),
    parseIgnore = require('parse-gitignore');

/* global describe, it */
describe('project repository', function () {
    var fs = require('fs');

    describe('package.json', function () {
        var content,
            json;

        try {
            content = fs.readFileSync('./package.json').toString();
            json = JSON.parse(content);
        }
        catch (e) {
            console.error(e);
            content = '';
            json = {};
        }

        it('must have readable JSON content', function () {
            expect(content).to.be.ok();
            expect(json).to.not.eql({});
        });

        describe('package.json JSON data', function () {
            it('must have valid name, description and author', function () {
                expect(json).to.have.property('name', 'newman');
                expect(json).to.have.property('description', 'Command-line companion utility for Postman');
                expect(json).to.have.property('author', 'Postman Labs <help@getpostman.com> (=)');
                expect(json).to.have.property('license', 'Apache-2.0');
                expect(json).to.have.property('homepage', 'https://github.com/postmanlabs/newman');
                expect(json).to.have.property('bugs', 'https://github.com/postmanlabs/newman/issues');

                expect(json).to.have.property('repository');
                expect(json.repository).to.eql({
                    type: 'git',
                    url: 'git://github.com/postmanlabs/newman.git'
                });

                expect(json).to.have.property('keywords');
                expect(json.keywords).to.eql(['newman', 'postman', 'api', 'testing', 'ci', 'rest-client', 'rest']);

                expect(json).to.have.property('engines');
                expect(json.engines).to.eql({ node: '>=4' });
            });

            it('must have a valid version string in form of <major>.<minor>.<revision>', function () {
                // eslint-disable-next-line max-len
                expect(json.version).to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/);
            });
        });

        describe('binary definitions', function () {
            it('must exist', function () {
                expect(json.bin).be.ok();
                expect(json.bin).to.eql({ 'newman': './bin/newman.js' });
            });

            it('must have valid node shebang', function () {
                json.bin && Object.keys(json.bin).forEach(function (scriptName) {
                    var fileContent = fs.readFileSync(json.bin[scriptName]).toString();
                    expect(/^#!\/(bin\/bash|usr\/bin\/env\snode)[\r\n][\W\w]*$/g.test(fileContent)).to.be.ok();
                });
            });
        });

        describe('script definitions', function () {
            it('files must exist', function () {
                expect(json.scripts).to.be.ok();
                json.scripts && Object.keys(json.scripts).forEach(function (scriptName) {
                    var name = json.scripts[scriptName];
                    name = name.replace(/^(node\s|\.\/)/, '');
                    fs.stat(name, function (err) {
                        var fileDetails = path.parse(name);
                        expect(err).to.equal(null);
                        expect(fileDetails.ext).to.be.oneOf(['.sh', '.js']);
                    });
                });
            });

            it('must have the hashbang defined', function () {
                expect(json.scripts).to.be.ok();
                json.scripts && Object.keys(json.scripts).forEach(function (scriptName) {
                    var name = json.scripts[scriptName];
                    name = name.replace(/^(node\s|\.\/)/, '');
                    fs.stat(name, function (err) {
                        var fileDetails = path.parse(name);
                        expect(err).to.equal(null);
                        expect(fileDetails.ext).to.be.oneOf(['.sh', '.js']);
                        fs.readFile(name, function (error, content) {
                            expect(error).to.equal(null);
                            if (fileDetails.ext === '.sh') {
                                expect(/^#!\/bin\/bash[\r\n][\W\w]*$/g.test(content)).to.be.ok();
                            }
                            else {
                                expect(/^#!\/usr\/bin\/env\snode[\r\n][\W\w]*$/g.test(content)).to.be.ok();
                            }
                        });
                    });
                });
            });
        });

        describe('dependencies', function () {
            it('must exist', function () {
                expect(json.dependencies).to.be.a('object');
            });

            it('must point to a valid and precise (no * or ^) semver', function () {
                json.dependencies && Object.keys(json.dependencies).forEach(function (item) {
                    expect(json.dependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });
        });

        describe('devDependencies', function () {
            it('must exist', function () {
                expect(json.devDependencies).to.be.a('object');
            });

            it('must point to a valid and precise (no * or ^) semver', function () {
                json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
                    expect(json.devDependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });

            it('should not overlap devDependencies', function () {
                var clean = [];

                json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
                    !json.dependencies[item] && clean.push(item);
                });

                expect(Object.keys(json.devDependencies)).to.eql(clean);
            });
        });

        describe('main entry script', function () {
            it('must point to a valid file', function (done) {
                expect(json.main).to.equal('index.js');
                fs.stat(json.main, done);
            });
        });
    });

    describe('README.md', function () {
        it('must exist', function (done) {
            fs.stat('./README.md', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./README.md').toString()).to.be.ok();
        });
    });

    describe('LICENSE.md', function () {
        it('must exist', function (done) {
            fs.stat('./LICENSE.md', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok();
        });
    });

    describe('.ignore files', function () {
        var gitignorePath = '.gitignore',
            npmignorePath = '.npmignore',
            npmignore = parseIgnore(npmignorePath),
            gitignore = parseIgnore(gitignorePath);

        describe(gitignorePath, function () {
            it('must exist', function (done) {
                fs.stat(gitignorePath, done);
            });

            it('must have valid content', function () {
                expect(_.isEmpty(gitignore)).to.not.be.ok();
            });
        });

        describe(npmignorePath, function () {
            it('must exist', function (done) {
                fs.stat(npmignorePath, done);
            });

            it('must have valid content', function () {
                expect(_.isEmpty(npmignore)).to.not.be.ok();
            });
        });

        it('.gitignore coverage must be a subset of .npmignore coverage', function () {
            expect(_.intersection(gitignore, npmignore)).to.eql(gitignore);
        });
    });

    describe('.eslintrc', function () {
        it('must exist', function (done) {
            fs.stat('./.eslintrc', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./.eslintrc').toString()).to.be.ok();
        });
    });

    describe('.nsprc', function () {
        it('must exist', function (done) {
            fs.stat('./.nsprc', done);
        });

        it('must have readable content', function () {
            expect(fs.readFileSync('./.nsprc').toString()).to.be.ok();
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var passport = require('passport-strategy')
    , auth_hdr = require('./auth_header')
    , util = require('util')
    , url = require('url')
    , _ = require('lodash');
/**
 * Strategy constructor
 *
 * @param options
 *          algorithms: (REQUIRED) object defining the configuration of for validating
 *          the JWT token per every algorithm i.e {"RS256": { ... options ... }
 *          jwtFromRequest: (REQUIRED) Function that accepts a reqeust as the only parameter and returns the either JWT as a string or null
 *          RS256.issuer: If defined issuer will be verified against this value
 *          RS256.audience: If defined audience will be verified against this value
 *          RS256.ignoreExpiration: if true do not validate the expiration of the token.
 *          RS256.passReqToCallback: If true the, the verify callback will be called with args (request, jwt_payload, done_callback).
 * @param verify - Verify callback with args (jwt_payload, done_callback) if passReqToCallback is false,
 *                 (request, jwt_payload, done_callback) if true.
 */
function MultiJwtStrategy(options, verify) {
    passport.Strategy.call(this);
    this.name = 'jwt';
    this._verify = verify;
    if (!this._verify) {
        throw new TypeError('MultiJwtStrategy requires a verify callback');
    }
    this._jwtFromRequest = options.jwtFromRequest;
    if (!this._jwtFromRequest) {
        throw new TypeError('MultiJwtStrategy requires a function to retrieve jwt from requests (see option jwtFromRequest)');
    }
    this._passReqToCallback = options.passReqToCallback;
    this._verifOpts = {};
    if (options.algorithms) {
        this._verifOpts.algorithms = options.algorithms;
    }
};
util.inherits(MultiJwtStrategy, passport.Strategy);
/**
 * Allow for injection of JWT Verifier.
 *
 * This improves testability by allowing tests to cleanly isolate failures in the JWT Verification
 * process from failures in the passport related mechanics of authentication.
 *
 * Note that this should only be replaced in tests.
 */
MultiJwtStrategy.JwtVerifier = require('./verify_jwt');
/**
 * Authenticate request based on JWT obtained from header or post body
 */
MultiJwtStrategy.prototype.authenticate = function(req, options) {
    var self = this;
    var token = self._jwtFromRequest(req);
    if (!token) {
        return self.fail(new Error("No auth token"));
    }
    var decodedToken;
    try {
        decodedToken = jws.decode(token, {});
    } catch(err) {
        return this.fail(new Error("Invalid token type"));
    }
    if(decodedToken === null)
        return this.fail(new Error("Invalid token type"));

    if(!_.has(decodedToken,'header') || !_.has(decodedToken.header,'alg'))
        return this.fail(new Error("Invalid token type"));

    if(!_.has(this._verifOpts.algorithms, decodedToken.header.alg))
        return this.fail(new Error("Invalid algorithm"));

    var options  =  this._verifOpts.algorithms[decodedToken.header.alg];
    options.algorithms = [decodedToken.header.alg];
    var secretOrKey = options.secretOrKey;
    delete options.secretOrKey;
    // Verify the JWT
    MultiJwtStrategy.JwtVerifier(token, secretOrKey, options, function(jwt_err, payload) {
        if (jwt_err) {
            return self.fail(jwt_err);
        } else {
            // Pass the parsed token to the user
            var verified = function(err, user, info) {
                if(err) {
                    return self.error(err);
                } else if (!user) {
                    return self.fail(info);
                } else {
                    return self.success(user, info);
                }
            };
            try {
                if (self._passReqToCallback) {
                    self._verify(req, payload, verified);
                } else {
                    self._verify(payload, verified);
                }
            } catch(ex) {
                self.error(ex);
            }
        }
    });
};

module.exports = MultiJwtStrategy;
<commit_msg>Improves error messages<commit_after>'use strict';

var passport = require('passport-strategy')
    , auth_hdr = require('./auth_header')
    , util = require('util')
    , url = require('url')
    , _ = require('lodash')
    , JsonWebTokenError = require('jsonwebtoken').JsonWebTokenError;
/**
 * Strategy constructor
 *
 * @param options
 *          algorithms: (REQUIRED) object defining the configuration of for validating
 *          the JWT token per every algorithm i.e {"RS256": { ... options ... }
 *          jwtFromRequest: (REQUIRED) Function that accepts a reqeust as the only parameter and returns the either JWT as a string or null
 *          RS256.issuer: If defined issuer will be verified against this value
 *          RS256.audience: If defined audience will be verified against this value
 *          RS256.ignoreExpiration: if true do not validate the expiration of the token.
 *          RS256.passReqToCallback: If true the, the verify callback will be called with args (request, jwt_payload, done_callback).
 * @param verify - Verify callback with args (jwt_payload, done_callback) if passReqToCallback is false,
 *                 (request, jwt_payload, done_callback) if true.
 */
function MultiJwtStrategy(options, verify) {
    passport.Strategy.call(this);
    this.name = 'jwt';
    this._verify = verify;
    if (!this._verify) {
        throw new TypeError('MultiJwtStrategy requires a verify callback');
    }
    this._jwtFromRequest = options.jwtFromRequest;
    if (!this._jwtFromRequest) {
        throw new TypeError('MultiJwtStrategy requires a function to retrieve jwt from requests (see option jwtFromRequest)');
    }
    this._passReqToCallback = options.passReqToCallback;
    this._verifOpts = {};
    if (options.algorithms) {
        this._verifOpts.algorithms = options.algorithms;
    }
};
util.inherits(MultiJwtStrategy, passport.Strategy);
/**
 * Allow for injection of JWT Verifier.
 *
 * This improves testability by allowing tests to cleanly isolate failures in the JWT Verification
 * process from failures in the passport related mechanics of authentication.
 *
 * Note that this should only be replaced in tests.
 */
MultiJwtStrategy.JwtVerifier = require('./verify_jwt');
/**
 * Authenticate request based on JWT obtained from header or post body
 */
MultiJwtStrategy.prototype.authenticate = function(req, options) {
    var self = this;
    var token = self._jwtFromRequest(req);
    if (!token) {
        return self.fail(new Error("No auth token"));
    }
    var decodedToken;
    try {
        decodedToken = jws.decode(token, {});
    } catch(err) {
        return this.fail(new JsonWebTokenError("Invalid token type"));
    }
    if(decodedToken === null)
        return this.fail(new JsonWebTokenError("Invalid token type"));

    if(!_.has(decodedToken,'header') || !_.has(decodedToken.header,'alg'))
        return this.fail(new JsonWebTokenError("Invalid token type"));

    if(!_.has(this._verifOpts.algorithms, decodedToken.header.alg))
        return this.fail(new JsonWebTokenError("Invalid algorithm"));

    var options  =  this._verifOpts.algorithms[decodedToken.header.alg];
    options.algorithms = [decodedToken.header.alg];
    var secretOrKey = options.secretOrKey;

    // Verify the JWT
    MultiJwtStrategy.JwtVerifier(token, secretOrKey, options, function(jwt_err, payload) {
        if (jwt_err) {
            return self.fail(jwt_err);
        } else {
            // Pass the parsed token to the user
            var verified = function(err, user, info) {
                if(err) {
                    return self.error(err);
                } else if (!user) {
                    return self.fail(info);
                } else {
                    return self.success(user, info);
                }
            };
            try {
                if (self._passReqToCallback) {
                    self._verify(req, payload, verified);
                } else {
                    self._verify(payload, verified);
                }
            } catch(ex) {
                self.error(ex);
            }
        }
    });
};

module.exports = MultiJwtStrategy;
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var util = require('util')
  , OAuth2Strategy = require('passport-oauth2')
  , Profile = require('./profile')
  , InternalOAuthError = require('passport-oauth2').InternalOAuthError;

/**
 * `Strategy` constructor.
 *
 * The GitHub authentication strategy authenticates requests by delegating to
 * GitHub using the OAuth 2.0 protocol.
 *
 * Applications must supply a `verify` callback which accepts an `accessToken`,
 * `refreshToken` and service-specific `profile`, and then calls the `done`
 * callback supplying a `user`, which should be set to `false` if the
 * credentials are not valid.  If an exception occured, `err` should be set.
 *
 * Options:
 *   - `clientID`      your GitHub application's Client ID
 *   - `clientSecret`  your GitHub application's Client Secret
 *   - `callbackURL`   URL to which GitHub will redirect the user after granting authorization
 *   - `scope`         array of permission scopes to request. Valid scopes include:
 *                     'user', 'public_repo', 'repo', 'gist', or none.
 *                     (see http://developer.github.com/v3/oauth/#scopes for more info)
 *   — `userAgent`     All API requests MUST include a valid User Agent string.
 *                     e.g: domain name of your application.
 *                     (see http://developer.github.com/v3/#user-agent-required for more info)
 *
 * Examples:
 *
 *     passport.use(new GitHubStrategy({
 *         clientID: '123-456-789',
 *         clientSecret: 'shhh-its-a-secret'
 *         callbackURL: 'https://www.example.net/auth/github/callback',
 *         userAgent: 'myapp.com'
 *       },
 *       function(accessToken, refreshToken, profile, done) {
 *         User.findOrCreate(..., function (err, user) {
 *           done(err, user);
 *         });
 *       }
 *     ));
 *
 * @param {Object} options
 * @param {Function} verify
 * @api public
 */
function Strategy(options, verify) {
  options = options || {};
  options.authorizationURL = options.authorizationURL || 'https://github.com/login/oauth/authorize';
  options.tokenURL = options.tokenURL || 'https://github.com/login/oauth/access_token';
  options.scopeSeparator = options.scopeSeparator || ',';
  options.customHeaders = options.customHeaders || {};

  if (!options.customHeaders['User-Agent']) {
    options.customHeaders['User-Agent'] = options.userAgent || 'passport-github';
  }

  OAuth2Strategy.call(this, options, verify);
  this.name = 'github';
  this._userProfileURL = options.userProfileURL || 'https://api.github.com/user';
  this._userEmailURL = options.userEmailURL || 'https://api.github.com/user/emails';
  this._oauth2.useAuthorizationHeaderforGET(true);
}

/**
 * Inherit from `OAuth2Strategy`.
 */
util.inherits(Strategy, OAuth2Strategy);

/**
 * Retrieve user profile from GitHub.
 *
 * This function constructs a normalized profile, with the following properties:
 *
 *   - `provider`         always set to `github`
 *   - `id`               the user's GitHub ID
 *   - `username`         the user's GitHub username
 *   - `displayName`      the user's full name
 *   - `profileUrl`       the URL of the profile for the user on GitHub
 *   - `emails`           the user's email addresses
 *
 * @param {String} accessToken
 * @param {Function} done
 * @api protected
 */
Strategy.prototype.userProfile = function(accessToken, done) {
  var self = this;

  this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
    var json;

    if (err) {
      return done(new InternalOAuthError('Failed to fetch user profile', err));
    }

    try {
      json = JSON.parse(body);
    } catch (ex) {
      return done(new Error('Failed to parse user profile'));
    }

    var profile = Profile.parse(json);
    profile.provider  = 'github';
    profile._raw = body;
    profile._json = json;

    // Getting emails
    self._oauth2.get(self._userEmailURL, accessToken, function (err, body, res) {
      if (err) {
        return done(new InternalOAuthError('Failed to fetch user emails', err));
      }

      var json = JSON.parse(body);

      for (var index in json) {
        if (json[index].primary) {
          profile.emails = [{ value: json[index].email }];
          break;
        }
      }

      done(null, profile);
    });
  });
};

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;
<commit_msg>request _userEmailURL when has user:email permission<commit_after>/**
 * Module dependencies.
 */
var util = require('util')
  , OAuth2Strategy = require('passport-oauth2')
  , Profile = require('./profile')
  , InternalOAuthError = require('passport-oauth2').InternalOAuthError;

/**
 * `Strategy` constructor.
 *
 * The GitHub authentication strategy authenticates requests by delegating to
 * GitHub using the OAuth 2.0 protocol.
 *
 * Applications must supply a `verify` callback which accepts an `accessToken`,
 * `refreshToken` and service-specific `profile`, and then calls the `done`
 * callback supplying a `user`, which should be set to `false` if the
 * credentials are not valid.  If an exception occured, `err` should be set.
 *
 * Options:
 *   - `clientID`      your GitHub application's Client ID
 *   - `clientSecret`  your GitHub application's Client Secret
 *   - `callbackURL`   URL to which GitHub will redirect the user after granting authorization
 *   - `scope`         array of permission scopes to request. Valid scopes include:
 *                     'user', 'public_repo', 'repo', 'gist', or none.
 *                     (see http://developer.github.com/v3/oauth/#scopes for more info)
 *   — `userAgent`     All API requests MUST include a valid User Agent string.
 *                     e.g: domain name of your application.
 *                     (see http://developer.github.com/v3/#user-agent-required for more info)
 *
 * Examples:
 *
 *     passport.use(new GitHubStrategy({
 *         clientID: '123-456-789',
 *         clientSecret: 'shhh-its-a-secret',
 *         callbackURL: 'https://www.example.net/auth/github/callback',
 *         userAgent: 'myapp.com'
 *       },
 *       function(accessToken, refreshToken, profile, done) {
 *         User.findOrCreate(..., function (err, user) {
 *           done(err, user);
 *         });
 *       }
 *     ));
 *
 * @param {Object} options
 * @param {Function} verify
 * @api public
 */
function Strategy(options, verify) {
  options = options || {};
  options.authorizationURL = options.authorizationURL || 'https://github.com/login/oauth/authorize';
  options.tokenURL = options.tokenURL || 'https://github.com/login/oauth/access_token';
  options.scopeSeparator = options.scopeSeparator || ',';
  options.customHeaders = options.customHeaders || {};

  if (!options.customHeaders['User-Agent']) {
    options.customHeaders['User-Agent'] = options.userAgent || 'passport-github';
  }

  OAuth2Strategy.call(this, options, verify);
  this.name = 'github';
  this._userProfileURL = options.userProfileURL || 'https://api.github.com/user';
  this._userEmailURL = options.userEmailURL || 'https://api.github.com/user/emails';
  this._oauth2.useAuthorizationHeaderforGET(true);
}

/**
 * Inherit from `OAuth2Strategy`.
 */
util.inherits(Strategy, OAuth2Strategy);

/**
 * Retrieve user profile from GitHub.
 *
 * This function constructs a normalized profile, with the following properties:
 *
 *   - `provider`         always set to `github`
 *   - `id`               the user's GitHub ID
 *   - `username`         the user's GitHub username
 *   - `displayName`      the user's full name
 *   - `profileUrl`       the URL of the profile for the user on GitHub
 *   - `emails`           the user's email addresses
 *
 * @param {String} accessToken
 * @param {Function} done
 * @api protected
 */
Strategy.prototype.userProfile = function(accessToken, done) {
  var self = this;

  this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
    var json;

    if (err) {
      return done(new InternalOAuthError('Failed to fetch user profile', err));
    }

    try {
      json = JSON.parse(body);
    } catch (ex) {
      return done(new Error('Failed to parse user profile'));
    }

    var profile = Profile.parse(json);
    profile.provider  = 'github';
    profile._raw = body;
    profile._json = json;

    var canAccessEmail = false;
    var scopes = self._scope;
    if (typeof scopes === 'string') {
      scopes = scopes.split(self._scopeSeparator);
    }
    if (Array.isArray(scopes)) {
      canAccessEmail = scopes.some(function(scope) {
        return scope === 'user' || scope === 'user:email';
      });
    }
    if (!canAccessEmail) {
      return done(null, profile);
    }

    // Getting emails
    self._oauth2.get(self._userEmailURL, accessToken, function (err, body, res) {
      if (err) {
        return done(new InternalOAuthError('Failed to fetch user emails', err));
      }

      var json = JSON.parse(body);

      for (var index in json) {
        if (json[index].primary) {
          profile.emails = [{ value: json[index].email }];
          break;
        }
      }

      done(null, profile);
    });
  });
};

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;
<|endoftext|>


<commit_before>/* jshint quotmark: false */
'use strict';

require('colors');

var FS = require('fs'),
    PATH = require('path'),
    SVGO = require('../svgo.js'),
    YAML = require('js-yaml'),
    PKG = require('../../package.json'),
    mkdirp = require('mkdirp'),
    encodeSVGDatauri = require('./tools.js').encodeSVGDatauri,
    decodeSVGDatauri = require('./tools.js').decodeSVGDatauri,
    regSVGFile = /\.svg$/;

/**
 * Command-Option-Argument.
 *
 * @see https://github.com/veged/coa
 */
module.exports = require('coa').Cmd()
    .helpful()
    .name(PKG.name)
    .title(PKG.description)
    .opt()
        .name('version').title('Version')
        .short('v').long('version')
        .only()
        .flag()
        .act(function() {
            // output the version to stdout instead of stderr if returned
            process.stdout.write(PKG.version + '\n');
            // coa will run `.toString` on the returned value and send it to stderr
            return '';
        })
        .end()
    .opt()
        .name('input').title('Input file, "-" for STDIN')
        .short('i').long('input')
        .val(function(val) {
            return val || this.reject("Option '--input' must have a value.");
        })
        .end()
    .opt()
        .name('string').title('Input SVG data string')
        .short('s').long('string')
        .end()
    .opt()
        .name('folder').title('Input folder, optimize and rewrite all *.svg files')
        .short('f').long('folder')
        .val(function(val) {
            return val || this.reject("Option '--folder' must have a value.");
        })
        .end()
    .opt()
        .name('output').title('Output file or folder (by default the same as the input), "-" for STDOUT')
        .short('o').long('output')
        .val(function(val) {
            return val || this.reject("Option '--output' must have a value.");
        })
        .end()
    .opt()
        .name('precision').title('Set number of digits in the fractional part, overrides plugins params')
        .short('p').long('precision')
        .val(function(val) {
            return !isNaN(val) ? val : this.reject("Option '--precision' must be an integer number");
        })
        .end()
    .opt()
        .name('config').title('Config file to extend or replace default')
        .long('config')
        .val(function(val) {
            return val || this.reject("Option '--config' must have a value.");
        })
        .end()
    .opt()
        .name('disable').title('Disable plugin by name')
        .long('disable')
        .arr()
        .val(function(val) {
            return val || this.reject("Option '--disable' must have a value.");
        })
        .end()
    .opt()
        .name('enable').title('Enable plugin by name')
        .long('enable')
        .arr()
        .val(function(val) {
            return val || this.reject("Option '--enable' must have a value.");
        })
        .end()
    .opt()
        .name('datauri').title('Output as Data URI string (base64, URI encoded or unencoded)')
        .long('datauri')
        .val(function(val) {
            return val || this.reject("Option '--datauri' must have one of the following values: 'base64', 'enc' or 'unenc'");
        })
        .end()
    .opt()
        .name('multipass').title('Enable multipass')
        .long('multipass')
        .flag()
        .end()
    .opt()
        .name('pretty').title('Make SVG pretty printed')
        .long('pretty')
        .flag()
        .end()
    .opt()
        .name('quiet').title('Only output error messages, not regular status messages')
        .short('q').long('quiet')
        .flag()
        .end()
    .opt()
        .name('show-plugins').title('Show available plugins and exit')
        .long('show-plugins')
        .flag()
        .end()
    .arg()
        .name('input').title('Alias to --input')
        .end()
    .arg()
        .name('output').title('Alias to --output')
        .end()
    .act(function(opts, args) {

        var input = args && args.input ? args.input : opts.input,
            output = args && args.output ? args.output : opts.output,
            config = {};

        // --show-plugins
        if (opts['show-plugins']) {

            showAvailablePlugins();
            process.exit(0);

        }

        // w/o anything
        if (
            (!input || input === '-') &&
            !opts.string &&
            !opts.stdin &&
            !opts.folder &&
            process.stdin.isTTY
        ) return this.usage();

        // --config
        if (opts.config) {

            // string
            if (opts.config.charAt(0) === '{') {
                try {
                    config = JSON.parse(opts.config);
                } catch (e) {
                    console.error("Error: Couldn't parse config JSON.");
                    console.error(String(e));
                    return;
                }

            // external file
            } else {
                var configPath = PATH.resolve(opts.config);
                try {
                    // require() adds some weird output on YML files
                    config = JSON.parse(FS.readFileSync(configPath, 'utf8'));
                } catch (err) {
                    if (err.code === 'ENOENT') {
                        console.error('Error: couldn\'t find config file \'' + opts.config + '\'.');
                        return;
                    } else if (err.code === 'EISDIR') {
                        console.error('Error: directory \'' + opts.config + '\' is not a config file.');
                        return;
                    }
                    config = YAML.safeLoad(FS.readFileSync(configPath, 'utf8'));

                    if (!config || Array.isArray(config)) {
                        console.error('Error: invalid config file \'' + opts.config + '\'.');
                        return;
                    }
                }
            }

        }

        // --quiet
        if (opts.quiet) {
            config.quiet = opts.quiet;
        }

        // --precision
        if (opts.precision) {
            config.floatPrecision = Math.max(0, parseInt(opts.precision));
        }

        // --disable
        if (opts.disable) {
            changePluginsState(opts.disable, false, config);
        }

        // --enable
        if (opts.enable) {
            changePluginsState(opts.enable, true, config);
        }

        // --multipass
        if (opts.multipass) {

            config.multipass = true;

        }

        // --pretty
        if (opts.pretty) {

            config.js2svg = config.js2svg || {};
            config.js2svg.pretty = true;

        }

        // --output
        if (opts.output) {
            config.output = opts.output;
        }

        // --folder
        if (opts.folder) {
            optimizeFolder(opts.folder, config, output);

            return;
        }

        // --input
        if (input) {

            // STDIN
            if (input === '-') {

                var data = '';

                process.stdin.pause();

                process.stdin
                    .on('data', function(chunk) {
                        data += chunk;
                    })
                    .once('end', function() {
                        optimizeFromString(data, config, opts.datauri, input, output);
                    })
                    .resume();

            // file
            } else {

                FS.readFile(input, 'utf8', function(err, data) {
                    if (err) {
                        if (err.code === 'EISDIR')
                            optimizeFolder(input, config, output);
                        else if (err.code === 'ENOENT')
                            console.error('Error: no such file or directory \'' + input + '\'.');
                        else
                            console.error(err);
                        return;
                    }
                    optimizeFromString(data, config, opts.datauri, input, output);
                });

            }

        // --string
        } else if (opts.string) {

            opts.string = decodeSVGDatauri(opts.string);

            optimizeFromString(opts.string, config, opts.datauri, input, output);

        }
    });

function optimizeFromString(svgstr, config, datauri, input, output) {

    var startTime = Date.now(config),
        time,
        inBytes = Buffer.byteLength(svgstr, 'utf8'),
        outBytes,
        svgo = new SVGO(config);

    svgo.optimize(svgstr, function(result) {

        if (result.error) {
            console.error(result.error);
            return;
        }

        if (datauri) {
            result.data = encodeSVGDatauri(result.data, datauri);
        }

        outBytes = Buffer.byteLength(result.data, 'utf8');
        time = Date.now() - startTime;

        // stdout
        if (output === '-' || (!input || input === '-') && !output) {

            process.stdout.write(result.data + '\n');

        // file
        } else {

            // overwrite input file if there is no output
            if (!output && input) {
                output = input;
            }

            if (!config.quiet) {
                console.log('\r');
            }

            saveFileAndPrintInfo(config, result.data, output, inBytes, outBytes, time);

        }

    });

}

function saveFileAndPrintInfo(config, data, path, inBytes, outBytes, time) {

    FS.writeFile(path, data, 'utf8', function() {
        if (config.quiet) {
            return;
        }

        // print time info
        printTimeInfo(time);

        // print optimization profit info
        printProfitInfo(inBytes, outBytes);

    });

}

function printTimeInfo(time) {
    console.log('Done in ' + time + ' ms!');

}

function printProfitInfo(inBytes, outBytes) {

    var profitPercents = 100 - outBytes * 100 / inBytes;

    console.log(
        (Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB' +
        (profitPercents < 0 ? ' + ' : ' - ') +
        String(Math.abs((Math.round(profitPercents * 10) / 10)) + '%').green + ' = ' +
        (Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB\n'
    );

}

/**
 * Change plugins state by names array.
 *
 * @param {Array} names plugins names
 * @param {Boolean} state active state
 * @param {Object} config original config
 * @return {Object} changed config
 */
function changePluginsState(names, state, config) {

    // extend config
    if (config.plugins) {

        names.forEach(function(name) {

            var matched,
                key;

            config.plugins.forEach(function(plugin) {

                // get plugin name
                if (typeof plugin === 'object') {
                    key = Object.keys(plugin)[0];
                } else {
                    key = plugin;
                }

                // if there is such a plugin name
                if (key === name) {
                    // don't replace plugin's params with true
                    if (typeof plugin[key] !== 'object' || !state) {
                        plugin[key] = state;
                    }

                    // mark it as matched
                    matched = true;
                }

            });

            // if not matched and current config is not full
            if (!matched && !config.full) {

                var obj = {};

                obj[name] = state;

                // push new plugin Object
                config.plugins.push(obj);

                matched = true;

            }

        });

    // just push
    } else {

        config.plugins = [];

        names.forEach(function(name) {
            var obj = {};

            obj[name] = state;

            config.plugins.push(obj);
        });

    }

    return config;

}

function optimizeFolder(dir, config, output) {

    var svgo = new SVGO(config);

    if (!config.quiet) {
        console.log('Processing directory \'' + dir + '\':\n');
    }

    // absoluted folder path
    var path = PATH.resolve(dir);

    // list folder content
    FS.readdir(path, function(err, files) {

        if (err) {
            console.error(err);
            return;
        }

        if (!files.length) {
            console.log('Directory \'' + dir + '\' is empty.');
            return;
        }

        var i = 0,
            found = false;

        function optimizeFile(file) {

            // absoluted file path
            var filepath = PATH.resolve(path, file);
            var outfilepath = output ? PATH.resolve(output, file) : filepath;

            // check if file name matches *.svg
            if (regSVGFile.test(filepath)) {

                found = true;
                FS.readFile(filepath, 'utf8', function(err, data) {

                    if (err) {
                        console.error(err);
                        return;
                    }

                    var startTime = Date.now(),
                        time,
                        inBytes = Buffer.byteLength(data, 'utf8'),
                        outBytes;

                    svgo.optimize(data, function(result) {

                        if (result.error) {
                            console.error(result.error);
                            return;
                        }

                        outBytes = Buffer.byteLength(result.data, 'utf8');
                        time = Date.now() - startTime;

                        writeOutput();

                        function writeOutput() {
                            FS.writeFile(outfilepath, result.data, 'utf8', report);
                        }

                        function report(err) {

                            if (err) {
                                if (err.code === 'ENOENT') {
                                    mkdirp(output, writeOutput);
                                    return;
                                } else if (err.code === 'ENOTDIR') {
                                    console.error('Error: output \'' + output + '\' is not a directory.');
                                    return;
                                }
                                console.error(err);
                                return;
                            }

                            if (!config.quiet) {
                                console.log(file + ':');

                                // print time info
                                printTimeInfo(time);

                                // print optimization profit info
                                printProfitInfo(inBytes, outBytes);
                            }

                            //move on to the next file
                            if (++i < files.length) {
                                optimizeFile(files[i]);
                            }

                        }

                    });

                });

            }
            //move on to the next file
            else if (++i < files.length) {
                optimizeFile(files[i]);
            } else if (!found) {
                console.log('No SVG files have been found.');
            }

        }

        optimizeFile(files[i]);

    });

}

var showAvailablePlugins = function () {

    var svgo = new SVGO();

    console.log('Currently available plugins:');

    svgo.config.plugins.forEach(function (plugins) {

        plugins.forEach(function (plugin) {

            console.log(' [ ' + plugin.name.green + ' ] ' + plugin.description);

        });

    });

    //console.log(JSON.stringify(svgo, null, 4));
};
<commit_msg>Show plugins list sorted alphabetically<commit_after>/* jshint quotmark: false */
'use strict';

require('colors');

var FS = require('fs'),
    PATH = require('path'),
    SVGO = require('../svgo.js'),
    YAML = require('js-yaml'),
    PKG = require('../../package.json'),
    mkdirp = require('mkdirp'),
    encodeSVGDatauri = require('./tools.js').encodeSVGDatauri,
    decodeSVGDatauri = require('./tools.js').decodeSVGDatauri,
    regSVGFile = /\.svg$/;

/**
 * Command-Option-Argument.
 *
 * @see https://github.com/veged/coa
 */
module.exports = require('coa').Cmd()
    .helpful()
    .name(PKG.name)
    .title(PKG.description)
    .opt()
        .name('version').title('Version')
        .short('v').long('version')
        .only()
        .flag()
        .act(function() {
            // output the version to stdout instead of stderr if returned
            process.stdout.write(PKG.version + '\n');
            // coa will run `.toString` on the returned value and send it to stderr
            return '';
        })
        .end()
    .opt()
        .name('input').title('Input file, "-" for STDIN')
        .short('i').long('input')
        .val(function(val) {
            return val || this.reject("Option '--input' must have a value.");
        })
        .end()
    .opt()
        .name('string').title('Input SVG data string')
        .short('s').long('string')
        .end()
    .opt()
        .name('folder').title('Input folder, optimize and rewrite all *.svg files')
        .short('f').long('folder')
        .val(function(val) {
            return val || this.reject("Option '--folder' must have a value.");
        })
        .end()
    .opt()
        .name('output').title('Output file or folder (by default the same as the input), "-" for STDOUT')
        .short('o').long('output')
        .val(function(val) {
            return val || this.reject("Option '--output' must have a value.");
        })
        .end()
    .opt()
        .name('precision').title('Set number of digits in the fractional part, overrides plugins params')
        .short('p').long('precision')
        .val(function(val) {
            return !isNaN(val) ? val : this.reject("Option '--precision' must be an integer number");
        })
        .end()
    .opt()
        .name('config').title('Config file to extend or replace default')
        .long('config')
        .val(function(val) {
            return val || this.reject("Option '--config' must have a value.");
        })
        .end()
    .opt()
        .name('disable').title('Disable plugin by name')
        .long('disable')
        .arr()
        .val(function(val) {
            return val || this.reject("Option '--disable' must have a value.");
        })
        .end()
    .opt()
        .name('enable').title('Enable plugin by name')
        .long('enable')
        .arr()
        .val(function(val) {
            return val || this.reject("Option '--enable' must have a value.");
        })
        .end()
    .opt()
        .name('datauri').title('Output as Data URI string (base64, URI encoded or unencoded)')
        .long('datauri')
        .val(function(val) {
            return val || this.reject("Option '--datauri' must have one of the following values: 'base64', 'enc' or 'unenc'");
        })
        .end()
    .opt()
        .name('multipass').title('Enable multipass')
        .long('multipass')
        .flag()
        .end()
    .opt()
        .name('pretty').title('Make SVG pretty printed')
        .long('pretty')
        .flag()
        .end()
    .opt()
        .name('quiet').title('Only output error messages, not regular status messages')
        .short('q').long('quiet')
        .flag()
        .end()
    .opt()
        .name('show-plugins').title('Show available plugins and exit')
        .long('show-plugins')
        .flag()
        .end()
    .arg()
        .name('input').title('Alias to --input')
        .end()
    .arg()
        .name('output').title('Alias to --output')
        .end()
    .act(function(opts, args) {

        var input = args && args.input ? args.input : opts.input,
            output = args && args.output ? args.output : opts.output,
            config = {};

        // --show-plugins
        if (opts['show-plugins']) {

            showAvailablePlugins();
            process.exit(0);

        }

        // w/o anything
        if (
            (!input || input === '-') &&
            !opts.string &&
            !opts.stdin &&
            !opts.folder &&
            process.stdin.isTTY
        ) return this.usage();

        // --config
        if (opts.config) {

            // string
            if (opts.config.charAt(0) === '{') {
                try {
                    config = JSON.parse(opts.config);
                } catch (e) {
                    console.error("Error: Couldn't parse config JSON.");
                    console.error(String(e));
                    return;
                }

            // external file
            } else {
                var configPath = PATH.resolve(opts.config);
                try {
                    // require() adds some weird output on YML files
                    config = JSON.parse(FS.readFileSync(configPath, 'utf8'));
                } catch (err) {
                    if (err.code === 'ENOENT') {
                        console.error('Error: couldn\'t find config file \'' + opts.config + '\'.');
                        return;
                    } else if (err.code === 'EISDIR') {
                        console.error('Error: directory \'' + opts.config + '\' is not a config file.');
                        return;
                    }
                    config = YAML.safeLoad(FS.readFileSync(configPath, 'utf8'));

                    if (!config || Array.isArray(config)) {
                        console.error('Error: invalid config file \'' + opts.config + '\'.');
                        return;
                    }
                }
            }

        }

        // --quiet
        if (opts.quiet) {
            config.quiet = opts.quiet;
        }

        // --precision
        if (opts.precision) {
            config.floatPrecision = Math.max(0, parseInt(opts.precision));
        }

        // --disable
        if (opts.disable) {
            changePluginsState(opts.disable, false, config);
        }

        // --enable
        if (opts.enable) {
            changePluginsState(opts.enable, true, config);
        }

        // --multipass
        if (opts.multipass) {

            config.multipass = true;

        }

        // --pretty
        if (opts.pretty) {

            config.js2svg = config.js2svg || {};
            config.js2svg.pretty = true;

        }

        // --output
        if (opts.output) {
            config.output = opts.output;
        }

        // --folder
        if (opts.folder) {
            optimizeFolder(opts.folder, config, output);

            return;
        }

        // --input
        if (input) {

            // STDIN
            if (input === '-') {

                var data = '';

                process.stdin.pause();

                process.stdin
                    .on('data', function(chunk) {
                        data += chunk;
                    })
                    .once('end', function() {
                        optimizeFromString(data, config, opts.datauri, input, output);
                    })
                    .resume();

            // file
            } else {

                FS.readFile(input, 'utf8', function(err, data) {
                    if (err) {
                        if (err.code === 'EISDIR')
                            optimizeFolder(input, config, output);
                        else if (err.code === 'ENOENT')
                            console.error('Error: no such file or directory \'' + input + '\'.');
                        else
                            console.error(err);
                        return;
                    }
                    optimizeFromString(data, config, opts.datauri, input, output);
                });

            }

        // --string
        } else if (opts.string) {

            opts.string = decodeSVGDatauri(opts.string);

            optimizeFromString(opts.string, config, opts.datauri, input, output);

        }
    });

function optimizeFromString(svgstr, config, datauri, input, output) {

    var startTime = Date.now(config),
        time,
        inBytes = Buffer.byteLength(svgstr, 'utf8'),
        outBytes,
        svgo = new SVGO(config);

    svgo.optimize(svgstr, function(result) {

        if (result.error) {
            console.error(result.error);
            return;
        }

        if (datauri) {
            result.data = encodeSVGDatauri(result.data, datauri);
        }

        outBytes = Buffer.byteLength(result.data, 'utf8');
        time = Date.now() - startTime;

        // stdout
        if (output === '-' || (!input || input === '-') && !output) {

            process.stdout.write(result.data + '\n');

        // file
        } else {

            // overwrite input file if there is no output
            if (!output && input) {
                output = input;
            }

            if (!config.quiet) {
                console.log('\r');
            }

            saveFileAndPrintInfo(config, result.data, output, inBytes, outBytes, time);

        }

    });

}

function saveFileAndPrintInfo(config, data, path, inBytes, outBytes, time) {

    FS.writeFile(path, data, 'utf8', function() {
        if (config.quiet) {
            return;
        }

        // print time info
        printTimeInfo(time);

        // print optimization profit info
        printProfitInfo(inBytes, outBytes);

    });

}

function printTimeInfo(time) {
    console.log('Done in ' + time + ' ms!');

}

function printProfitInfo(inBytes, outBytes) {

    var profitPercents = 100 - outBytes * 100 / inBytes;

    console.log(
        (Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB' +
        (profitPercents < 0 ? ' + ' : ' - ') +
        String(Math.abs((Math.round(profitPercents * 10) / 10)) + '%').green + ' = ' +
        (Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB\n'
    );

}

/**
 * Change plugins state by names array.
 *
 * @param {Array} names plugins names
 * @param {Boolean} state active state
 * @param {Object} config original config
 * @return {Object} changed config
 */
function changePluginsState(names, state, config) {

    // extend config
    if (config.plugins) {

        names.forEach(function(name) {

            var matched,
                key;

            config.plugins.forEach(function(plugin) {

                // get plugin name
                if (typeof plugin === 'object') {
                    key = Object.keys(plugin)[0];
                } else {
                    key = plugin;
                }

                // if there is such a plugin name
                if (key === name) {
                    // don't replace plugin's params with true
                    if (typeof plugin[key] !== 'object' || !state) {
                        plugin[key] = state;
                    }

                    // mark it as matched
                    matched = true;
                }

            });

            // if not matched and current config is not full
            if (!matched && !config.full) {

                var obj = {};

                obj[name] = state;

                // push new plugin Object
                config.plugins.push(obj);

                matched = true;

            }

        });

    // just push
    } else {

        config.plugins = [];

        names.forEach(function(name) {
            var obj = {};

            obj[name] = state;

            config.plugins.push(obj);
        });

    }

    return config;

}

function optimizeFolder(dir, config, output) {

    var svgo = new SVGO(config);

    if (!config.quiet) {
        console.log('Processing directory \'' + dir + '\':\n');
    }

    // absoluted folder path
    var path = PATH.resolve(dir);

    // list folder content
    FS.readdir(path, function(err, files) {

        if (err) {
            console.error(err);
            return;
        }

        if (!files.length) {
            console.log('Directory \'' + dir + '\' is empty.');
            return;
        }

        var i = 0,
            found = false;

        function optimizeFile(file) {

            // absoluted file path
            var filepath = PATH.resolve(path, file);
            var outfilepath = output ? PATH.resolve(output, file) : filepath;

            // check if file name matches *.svg
            if (regSVGFile.test(filepath)) {

                found = true;
                FS.readFile(filepath, 'utf8', function(err, data) {

                    if (err) {
                        console.error(err);
                        return;
                    }

                    var startTime = Date.now(),
                        time,
                        inBytes = Buffer.byteLength(data, 'utf8'),
                        outBytes;

                    svgo.optimize(data, function(result) {

                        if (result.error) {
                            console.error(result.error);
                            return;
                        }

                        outBytes = Buffer.byteLength(result.data, 'utf8');
                        time = Date.now() - startTime;

                        writeOutput();

                        function writeOutput() {
                            FS.writeFile(outfilepath, result.data, 'utf8', report);
                        }

                        function report(err) {

                            if (err) {
                                if (err.code === 'ENOENT') {
                                    mkdirp(output, writeOutput);
                                    return;
                                } else if (err.code === 'ENOTDIR') {
                                    console.error('Error: output \'' + output + '\' is not a directory.');
                                    return;
                                }
                                console.error(err);
                                return;
                            }

                            if (!config.quiet) {
                                console.log(file + ':');

                                // print time info
                                printTimeInfo(time);

                                // print optimization profit info
                                printProfitInfo(inBytes, outBytes);
                            }

                            //move on to the next file
                            if (++i < files.length) {
                                optimizeFile(files[i]);
                            }

                        }

                    });

                });

            }
            //move on to the next file
            else if (++i < files.length) {
                optimizeFile(files[i]);
            } else if (!found) {
                console.log('No SVG files have been found.');
            }

        }

        optimizeFile(files[i]);

    });

}

var showAvailablePlugins = function () {

    var svgo = new SVGO(),
        // Flatten an array of plugins grouped per type and sort alphabetically
        list = Array.prototype.concat.apply([], svgo.config.plugins).sort(function(a, b) {
            return a.name > b.name ? 1 : -1;
        });;

    console.log('Currently available plugins:');

    list.forEach(function (plugin) {
        console.log(' [ ' + plugin.name.green + ' ] ' + plugin.description);
    });

    //console.log(JSON.stringify(svgo, null, 4));
};
<|endoftext|>


<commit_before>
/*
 Virtual dom is an array of custom tags on the document.
 Updates and unmounts propagate downwards from parent to children.
 */

var virtualDom = [],
  tagImpl = {}

function getTag(dom) {
  return tagImpl[dom.getAttribute('riot-tag') || dom.tagName.toLowerCase()]
}

function injectStyle(css) {
  var node = document.createElement('style')
  node.innerHTML = css
  document.head.appendChild(node)
}

function mountTo(root, tagName, opts) {
  var tag = tagImpl[tagName],
    innerHTML = root.innerHTML

  // clear the inner html
  root.innerHTML = ''

  if (tag && root) tag = new Tag(tag, { root: root, opts: opts }, innerHTML)

  if (tag && tag.mount) {
    tag.mount()
    virtualDom.push(tag)
    return tag.on('unmount', function() {
      virtualDom.splice(virtualDom.indexOf(tag), 1)
    })
  }

}

riot.tag = function(name, html, css, fn) {
  if (typeof css == 'function') fn = css
  else if (css) injectStyle(css)
  tagImpl[name] = { name: name, tmpl: html, fn: fn }
  return name
}

riot.mount = function(selector, tagName, opts) {

  var el,
    selctAllTags = function(sel) {
      sel = Object.keys(tagImpl).join(', ')
      sel.split(',').map(function(t) {
        sel += ', *[riot-tag="'+ t.trim() + '"]'
      })
      return sel
    },
    tags = []

  if (typeof tagName == 'object') { opts = tagName; tagName = 0 }

  // crawl the DOM to find the tag
  if(typeof selector == 'string') {
    if (selector == '*') {
      // select all the tags registered
      // and also the tags found with the riot-tag attribute set
      selector = selctAllTags(selector)
    } else {
      selector.split(',').map(function(t) {
        selector += ', *[riot-tag="'+ t.trim() + '"]'
      })

    }
    // or just the ones named like the selector
    el = $$(selector)
  }
  // probably you have passed already a tag or a NodeList
  else
    el = selector

  // select all the registered and mount them inside their root elements
  if (tagName == '*') {
    // get all custom tags
    tagName = selctAllTags(selector)
    // if the root el it's just a single tag
    if (el.tagName) {
      el = $$(tagName, el)
    } else {
      var nodeList = []
      // select all the children for all the different root elements
      each(el, function(tag) {
        nodeList = $$(tagName, tag)
      })
      el = nodeList
    }
    // get rid of the tagName
    tagName = 0
  }

  function push(root) {
    var name = tagName || root.getAttribute('riot-tag') || root.tagName.toLowerCase(),
      tag = mountTo(root, name, opts)

    if (tag) tags.push(tag)
  }

  // DOM node
  if (el.tagName)
    push(selector)
  // selector or NodeList
  else
    each(el, push)

  return tags

}

// update everything
riot.update = function() {
  return each(virtualDom, function(tag) {
    tag.update()
  })
}

// @deprecated
riot.mountTo = riot.mount

<commit_msg>clean indents<commit_after>
/*
 Virtual dom is an array of custom tags on the document.
 Updates and unmounts propagate downwards from parent to children.
*/

var virtualDom = [],
    tagImpl = {}

function getTag(dom) {
  return tagImpl[dom.getAttribute('riot-tag') || dom.tagName.toLowerCase()]
}

function injectStyle(css) {
  var node = document.createElement('style')
  node.innerHTML = css
  document.head.appendChild(node)
}

function mountTo(root, tagName, opts) {
  var tag = tagImpl[tagName],
      innerHTML = root.innerHTML

  // clear the inner html
  root.innerHTML = ''

  if (tag && root) tag = new Tag(tag, { root: root, opts: opts }, innerHTML)

  if (tag && tag.mount) {
    tag.mount()
    virtualDom.push(tag)
    return tag.on('unmount', function() {
      virtualDom.splice(virtualDom.indexOf(tag), 1)
    })
  }

}

riot.tag = function(name, html, css, fn) {
  if (typeof css == 'function') fn = css
  else if (css) injectStyle(css)
  tagImpl[name] = { name: name, tmpl: html, fn: fn }
  return name
}

riot.mount = function(selector, tagName, opts) {

  var el,
      selctAllTags = function(sel) {
        sel = Object.keys(tagImpl).join(', ')
        sel.split(',').map(function(t) {
          sel += ', *[riot-tag="'+ t.trim() + '"]'
        })
        return sel
      },
      tags = []

  if (typeof tagName == 'object') { opts = tagName; tagName = 0 }

  // crawl the DOM to find the tag
  if(typeof selector == 'string') {
    if (selector == '*') {
      // select all the tags registered
      // and also the tags found with the riot-tag attribute set
      selector = selctAllTags(selector)
    } else {
      selector.split(',').map(function(t) {
        selector += ', *[riot-tag="'+ t.trim() + '"]'
      })

    }
    // or just the ones named like the selector
    el = $$(selector)
  }
  // probably you have passed already a tag or a NodeList
  else
    el = selector

  // select all the registered and mount them inside their root elements
  if (tagName == '*') {
    // get all custom tags
    tagName = selctAllTags(selector)
    // if the root el it's just a single tag
    if (el.tagName) {
      el = $$(tagName, el)
    } else {
      var nodeList = []
      // select all the children for all the different root elements
      each(el, function(tag) {
        nodeList = $$(tagName, tag)
      })
      el = nodeList
    }
    // get rid of the tagName
    tagName = 0
  }

  function push(root) {
    var name = tagName || root.getAttribute('riot-tag') || root.tagName.toLowerCase(),
        tag = mountTo(root, name, opts)

    if (tag) tags.push(tag)
  }

  // DOM node
  if (el.tagName)
    push(selector)
  // selector or NodeList
  else
    each(el, push)

  return tags

}

// update everything
riot.update = function() {
  return each(virtualDom, function(tag) {
    tag.update()
  })
}

// @deprecated
riot.mountTo = riot.mount

<|endoftext|>


<commit_before>const _ = require('lodash')

export function render(src, vars = {}) {
  vars = _.merge({}, process.env, vars)
  return processTemplate(vars)(src)
}

function processTemplate(vars) {
  return function replace(src) {
    switch (true) {
      case typeof src === 'string':
        src = replaceString(src, vars)
        break
      case Array.isArray(src):
        src = src.map(replace)
        break
      case _.isPlainObject(src):
        src = _.mapValues(src, replace)
        break
    }
    return src
  }
}

const expression = /\$\{([^\}]+)?\}/g

function replaceString(str, vars) {
  return str.replace(expression, (_, match) => {
    return getKey(match, vars)
  })
}

function getKey(key, obj) {
  let value = obj[key] || obj[key.toUpperCase()] || obj[key.toLowerCase()] || null
  if (value == null) {
    throw new Error('Missing variable to replace: ${' + key + '}. Have you defined it?')
  }
  return value
}
<commit_msg>refactor(template): template string<commit_after>const _ = require('lodash')

export function render(src, vars = {}) {
  vars = _.merge({}, process.env, vars)
  return processTemplate(vars)(src)
}

function processTemplate(vars) {
  return function replace(src) {
    switch (true) {
      case typeof src === 'string':
        src = replaceString(src, vars)
        break
      case Array.isArray(src):
        src = src.map(replace)
        break
      case _.isPlainObject(src):
        src = _.mapValues(src, replace)
        break
    }
    return src
  }
}

const expression = /\$\{([^\}]+)?\}/g

function replaceString(str, vars) {
  return str.replace(expression, (_, match) => {
    return getKey(match, vars)
  })
}

function getKey(key, obj) {
  let value = obj[key] || obj[key.toUpperCase()] || obj[key.toLowerCase()] || null
  if (value == null) {
    throw new Error(`Missing variable to replace: \$\{${key}\}". Have you defined it?`)
  }
  return value
}
<|endoftext|>


<commit_before>let estemplate = {}
let ast = {type: 'Program', body: [], sourceType: 'script'}

estemplate.ast = () => ast

estemplate.literal = (value, raw) => {
  if (raw === undefined) {
    return {type: 'Literal', value: value}
  }
  return {type: 'Literal', value: value, raw: raw}
}

estemplate.stringliteral = value => {
  return {type: 'StringLiteral', value: '"' + value + '"'}
}

estemplate.identifier = value => {
  return {type: 'Identifier', name: value}
}

estemplate.funcdeclaration = (val, params) => {
  return {
    type: 'VariableDeclaration',
    declarations: [
      {
        type: 'VariableDeclarator',
        id: val,
        init: {
          type: 'ArrowFunctionExpression',
          id: null,
          params: params,
          body: {},
          generator: false,
          expression: true
        }
      }
    ],
    kind: 'const'}
}

estemplate.fnCall = (val, args) => {
  return {
    type: 'ExpressionStatement',
    expression: {
      type: 'CallExpression',
      callee: val,
      arguements: args
    }
  }
}

estemplate.declaration = (id, val) => {
  return {
    type: 'VariableDeclaration',
    declarations: [
      {
        type: 'VariableDeclarator',
        id: id,
        init: val
      }
    ],
    kind: 'const'
  }
}

/*  Module Exports estemplate  */
module.exports = estemplate
<commit_msg>minor structural changes<commit_after>let estemplate = {}

estemplate.ast = () =>
  ({type: 'Program', body: [], sourceType: 'script'})

estemplate.literal = value =>
  ({type: 'Literal', value: Number(value), raw: value})

estemplate.stringLiteral = value =>
  ({type: 'Literal', value: value, raw: '"' + value + '"'})

estemplate.identifier = value =>
  ({type: 'Identifier', name: value})

estemplate.funcDeclaration = (...val) => (
  {
    type: 'VariableDeclaration',
    declarations: [
      {
        type: 'VariableDeclarator',
        id: val[0],
        init: {
          type: 'ArrowFunctionExpression',
          id: null,
          params: val[1],
          body: val[2] || '',
          generator: false,
          expression: true
        }
      }
    ],
    kind: 'const'
  }
)

estemplate.fnCall = (val, args) => (
  {
    type: 'ExpressionStatement',
    expression: {
      type: 'CallExpression',
      callee: val,
      arguments: args
    }
  }
)

estemplate.declaration = (id, val) => (
  {
    type: 'VariableDeclaration',
    declarations: [
      {
        type: 'VariableDeclarator',
        id: id,
        init: val
      }
    ],
    kind: 'const'
  }
)

/*  Module Exports estemplate  */
module.exports = estemplate
<|endoftext|>


<commit_before>'use strict';

const chai = require('chai'),
  sinon = require('sinon'),
  expect = chai.expect,
  Support   = require('../support'),
  DataTypes = require('../../../lib/data-types'),
  current   = Support.sequelize;

describe(Support.getTestDialectTeaser('Instance'), () => {
  describe('get', () => {
    beforeEach(function() {
      this.getSpy = sinon.spy();
      this.User = current.define('User', {
        name: {
          type: DataTypes.STRING,
          get: this.getSpy
        }
      });
    });

    it('invokes getter if raw: false', function() {
      this.User.build().get('name');

      expect(this.getSpy).to.have.been.called;
    });

    it('does not invoke getter if raw: true', function() {
      expect(this.getSpy, { raw: true }).not.to.have.been.called;
    });
  });
});
<commit_msg>fix(test): actually test get method with raw option (#10059)<commit_after>'use strict';

const chai = require('chai'),
  sinon = require('sinon'),
  expect = chai.expect,
  Support   = require('../support'),
  DataTypes = require('../../../lib/data-types'),
  current   = Support.sequelize;

describe(Support.getTestDialectTeaser('Instance'), () => {
  describe('get', () => {
    beforeEach(function() {
      this.getSpy = sinon.spy();
      this.User = current.define('User', {
        name: {
          type: DataTypes.STRING,
          get: this.getSpy
        }
      });
    });

    it('invokes getter if raw: false', function() {
      this.User.build().get('name');

      expect(this.getSpy).to.have.been.called;
    });

    it('does not invoke getter if raw: true', function() {
      this.User.build().get('name', { raw: true });

      expect(this.getSpy).not.to.have.been.called;
    });
  });
});
<|endoftext|>


<commit_before>'use strict'

let test = require('zopf')
let proxyquire = require('proxyquire')

let electron = require('../stubs/electron')

let setup = t => {
  let os = {}

  let stubs = Object.assign({
    './os': os
  }, electron)

  let updater = proxyquire('../../app/util/auto-updater', stubs)
  return Object.assign({updater, os}, electron)
}

let setup_win32 = t => {
  let os = {}

  let stubs = Object.assign({
    '../os': os
  }, electron)

  let win32 = proxyquire('../../app/util/auto-updater/win32', stubs)
  return Object.assign({os, win32}, electron.electron)
}

test('auto-updater', t => {
  t.case('stubbed on darwin', t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('darwin')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })

  t.case('bypassed on linux', t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('linux')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })
})

test('auto-updater/win32', t => {
  t.case(`noop if no squirrel command`, t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('win32')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })

  ;['install', 'updated', 'uninstall', 'obsolete'].forEach((action) => {
    t.case(`quit on ${action}`, t => {
      let r = setup_win32(t)
      t.stub(r.os, 'cli_args').returns(['hi mom', `--squirrel-${action}`])
      Promise.resolve(r.win32.start()).then((r) => {
        t.true(r, 'returns true')
      })
    })
  })
})
<commit_msg>don't actually run reg during tests<commit_after>'use strict'

let test = require('zopf')
let proxyquire = require('proxyquire')

let electron = require('../stubs/electron')

let setup = t => {
  let os = {}

  let stubs = Object.assign({
    './os': os
  }, electron)

  let updater = proxyquire('../../app/util/auto-updater', stubs)
  return Object.assign({updater, os}, electron)
}

let setup_win32 = t => {
  let os = {}
  let reg = {
    install: async () => null,
    uninstall: async () => null
  }

  let stubs = Object.assign({
    '../os': os,
    '../reg': reg
  }, electron)

  let win32 = proxyquire('../../app/util/auto-updater/win32', stubs)
  return Object.assign({os, win32}, electron.electron)
}

test('auto-updater', t => {
  t.case('stubbed on darwin', t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('darwin')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })

  t.case('bypassed on linux', t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('linux')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })
})

test('auto-updater/win32', t => {
  t.case(`noop if no squirrel command`, t => {
    let r = setup(t)
    t.stub(r.os, 'platform').returns('win32')
    Promise.resolve(r.updater.start()).then((r) => {
      t.false(r, 'returns false')
    })
  })

  ;['install', 'updated', 'uninstall', 'obsolete'].forEach((action) => {
    t.case(`quit on ${action}`, t => {
      let r = setup_win32(t)
      t.stub(r.os, 'cli_args').returns(['hi mom', `--squirrel-${action}`])
      Promise.resolve(r.win32.start()).then((r) => {
        t.true(r, 'returns true')
      })
    })
  })
})
<|endoftext|>


<commit_before>(function(root) {

var Substance = root.Substance;

var impl = {
  setup: function() {
  }
};

var test = new Substance.test.PersistentIndexTest(impl);
Substance.registerTest(["Store", "PersistentIndex", "MemoryStore"], test);

})(this);
<commit_msg>Remove obsolete test.<commit_after><|endoftext|>


<commit_before>export default [{
    clientExtensions: {},
    database: 'mysql',
    enableDeveloperExperiments: true,
    environment: 'development',
    labs: {},
    mail: 'SMTP',
    version: '2.15.0',
    useGravatar: 'true'
}];
<commit_msg>Default developer experiments to "off" in tests<commit_after>export default [{
    clientExtensions: {},
    database: 'mysql',
    enableDeveloperExperiments: false,
    environment: 'development',
    labs: {},
    mail: 'SMTP',
    version: '2.15.0',
    useGravatar: 'true'
}];
<|endoftext|>


<commit_before>/**
 * Polls the server directory every second to detect a file change independently
 * of the parent process.
 *
 * Sends a string of double quote-space separated paths to the parent process
 * upon detection of a file change. Note that this does not scale well with
 * many files to keep track of.
 */
var fs = require ('fs'), S = require ('os').platform ().match (/^win\d+?/)? '\\' : '/', allPaths = bfs (__dirname), SECONDS = 1, p = process;
console.log ('\n"dir_watch.js" child process started! S: ' + S);

allPaths.sort ();
process.send (concat (allPaths));

setInterval (updatePaths, SECONDS * 1000);

function updatePaths () {
	var d = bfs (__dirname);

	// Small optimization for speedup
	d.length !== allPaths.length? _true () : _false ();

	function _true () {allPaths = d; p.send (concat (d));}
	function _false () {d.sort (); for (var i = 0; i < d.length; i++) if (allPaths[i] !== d[i]) {allPaths = d; p.send (concat (d)); break;}}
}

/* Called before process.send to process the list of files and directories to avoid blockage in the parent process */
function concat (array) {
	// Use a new array to avoid mutation errors that cause the directory to be read at every tick of this function
	var newArray = [];

	// Remove the path leading to index.js for easier reading in the parent function
	for (var i = 0; i < array.length; i++) newArray.push (array[i].replace (new RegExp ('^' + deRegEx (__dirname)), '').replace (/\\/g, '/'));
	return ['Update Directory', '"' + newArray.join ('" "') + '"'];
}

/* Recursive breadth-first search that constructs a list of all files relative to __dirname */
function bfs (dirStr) {
	var dirs = [dirStr], all = [], dir;

	function bfsWorker (path) {
		try {
			dir = fs.readdirSync (path);
			dir.length? (function () {for (var i = 0; i < dir.length; i++) dirs.push (path + S + dir[i]);})() : all.push (path + ':DIRECTORY');
		} catch (error) {
			error.code === 'ENOTDIR'? all.push (path + ':FILE') : console.log ('UNKNOWN ERROR OCCURRED:\n' + error + '\n');
		}

		if (dirs.length) bfsWorker (dirs.splice (0, 1)[0]);
	}

	bfsWorker (dirs.splice (0, 1)[0]);
	return all;
}

/* Used to cleanly dynamically generate RegEx from a string literal using new RegExp */
function deRegEx (str) {
	return str.replace (/\\/g, '\\\\')
		.replace (/\//g, '\\/')
		.replace (/\?/g, '\\?')
		.replace (/\+/g, '\\+')
		.replace (/\[/g, '\\[')
		.replace (/\]/g, '\\]')
		.replace (/\{/g, '\\{')
		.replace (/\}/g, '\\}')
		.replace (/\./g, '\\.')
		.replace (/\*/g, '\\*')
		.replace (/\^/g, '\\^')
		.replace (/\$/, '\\$')
		.replace (/\(/g, '\\(')
		.replace (/\)/g, '\\)')
		.replace (/\|/g, '\\|');
}
<commit_msg>Changed setInterval to setTimeout to avoid cyclical processing, and sped up the polling interval from 1 second to 0.25 seconds as it seems the machine can handle it just fine.<commit_after>/**
 * Polls the server directory every second to detect a file change independently
 * of the parent process.
 *
 * Sends a string of double quote-space separated paths to the parent process
 * upon detection of a file change. Note that this does not scale well with
 * many files to keep track of.
 */
var fs = require ('fs'), S = require ('os').platform ().match (/^win\d+?/)? '\\' : '/', allPaths = bfs (__dirname), SECONDS = 0.5, p = process;
console.log ('\n"dir_watch.js" child process started! S: ' + S);

allPaths.sort ();
process.send (concat (allPaths));

updatePaths ();

function updatePaths () {
	var d = bfs (__dirname);

	// Small optimization for speedup
	d.length !== allPaths.length? _true () : _false ();

	function _true () {allPaths = d; p.send (concat (d));}
	function _false () {d.sort (); for (var i = 0; i < d.length; i++) if (allPaths[i] !== d[i]) {allPaths = d; p.send (concat (d)); break;}}

	setTimeout (updatePaths, SECONDS * 1000);
}

/* Called before process.send to process the list of files and directories to avoid blockage in the parent process */
function concat (array) {
	// Use a new array to avoid mutation errors that cause the directory to be read at every tick of this function
	var newArray = [];

	// Remove the path leading to index.js for easier reading in the parent function
	for (var i = 0; i < array.length; i++) newArray.push (array[i].replace (new RegExp ('^' + deRegEx (__dirname)), '').replace (/\\/g, '/'));
	return ['Update Directory', '"' + newArray.join ('" "') + '"'];
}

/* Recursive breadth-first search that constructs a list of all files relative to __dirname */
function bfs (dirStr) {
	var dirs = [dirStr], all = [], dir;

	function bfsWorker (path) {
		try {
			dir = fs.readdirSync (path);
			dir.length? (function () {for (var i = 0; i < dir.length; i++) dirs.push (path + S + dir[i]);})() : all.push (path + ':DIRECTORY');
		} catch (error) {
			error.code === 'ENOTDIR'? all.push (path + ':FILE') : console.log ('UNKNOWN ERROR OCCURRED:\n' + error + '\n');
		}

		if (dirs.length) bfsWorker (dirs.splice (0, 1)[0]);
	}

	bfsWorker (dirs.splice (0, 1)[0]);
	return all;
}

/* Used to cleanly dynamically generate RegEx from a string literal using new RegExp */
function deRegEx (str) {
	return str.replace (/\\/g, '\\\\')
		.replace (/\//g, '\\/')
		.replace (/\?/g, '\\?')
		.replace (/\+/g, '\\+')
		.replace (/\[/g, '\\[')
		.replace (/\]/g, '\\]')
		.replace (/\{/g, '\\{')
		.replace (/\}/g, '\\}')
		.replace (/\./g, '\\.')
		.replace (/\*/g, '\\*')
		.replace (/\^/g, '\\^')
		.replace (/\$/, '\\$')
		.replace (/\(/g, '\\(')
		.replace (/\)/g, '\\)')
		.replace (/\|/g, '\\|');
}
<|endoftext|>


<commit_before>var isMobile;

$(document)
  .ready(function(){
    detechMobile();
    if( isMobile.any() ) alert('Mobile');
  });

  function detechMobile() {
    isMobile = {
      Android: function() {
          return navigator.userAgent.match(/Android/i);
      },
      BlackBerry: function() {
          return navigator.userAgent.match(/BlackBerry/i);
      },
      iOS: function() {
          return navigator.userAgent.match(/iPhone|iPad|iPod/i);
      },
      Opera: function() {
          return navigator.userAgent.match(/Opera Mini/i);
      },
      Windows: function() {
          return navigator.userAgent.match(/IEMobile/i);
      },
      any: function() {
          return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
      }
    };
  }<commit_msg>updated base javascript file<commit_after>$(document).ready(function(){
  $('.dropdown').dropdown();
  $('.checkbox').checkbox();
});<|endoftext|>