<commit_before>define("ace/mode/toml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var TomlHighlightRules = function() {
    var keywordMapper = this.createKeywordMapper({
        "constant.language.boolean": "true|false"
    }, "identifier");

    var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b";

    this.$rules = {
    "start": [
        {
            token: "comment.toml",
            regex: /#.*$/
        },
        {
            token : "string",
            regex : '"(?=.)',
            next  : "qqstring"
        },
        {
            token: ["variable.keygroup.toml"],
            regex: "(?:^\\s*)(\\[\\[([^\\]]+)\\]\\])"
        },
        {
            token: ["variable.keygroup.toml"],
            regex: "(?:^\\s*)(\\[([^\\]]+)\\])"
        },
        {
            token : keywordMapper,
            regex : identifierRe
        },
        {
           token : "support.date.toml",
           regex: "\\d{4}-\\d{2}-\\d{2}(T)\\d{2}:\\d{2}:\\d{2}(Z)"
        },
        {
           token: "constant.numeric.toml",
           regex: "-?\\d+(\\.?\\d+)?"
        }
    ],
    "qqstring" : [
        {
            token : "string",
            regex : "\\\\$",
            next  : "qqstring"
        },
        {
            token : "constant.language.escape",
            regex : '\\\\[0tnr"\\\\]'
        },
        {
            token : "string",
            regex : '"|$',
            next  : "start"
        },
        {
            defaultToken: "string"
        }
    ]
    }

};

oop.inherits(TomlHighlightRules, TextHighlightRules);

exports.TomlHighlightRules = TomlHighlightRules;
});

define("ace/mode/folding/ini",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var Range = require("../../range").Range;
var BaseFoldMode = require("./fold_mode").FoldMode;

var FoldMode = exports.FoldMode = function() {
};
oop.inherits(FoldMode, BaseFoldMode);

(function() {

    this.foldingStartMarker = /^\s*\[([^\])]*)]\s*(?:$|[;#])/;

    this.getFoldWidgetRange = function(session, foldStyle, row) {
        var re = this.foldingStartMarker;
        var line = session.getLine(row);

        var m = line.match(re);

        if (!m) return;

        var startName = m[1] + ".";

        var startColumn = line.length;
        var maxRow = session.getLength();
        var startRow = row;
        var endRow = row;

        while (++row < maxRow) {
            line = session.getLine(row);
            if (/^\s*$/.test(line))
                continue;
            m = line.match(re);
            if (m && m[1].lastIndexOf(startName, 0) !== 0)
                break;

            endRow = row;
        }

        if (endRow > startRow) {
            var endColumn = session.getLine(endRow).length;
            return new Range(startRow, startColumn, endRow, endColumn);
        }
    };

}).call(FoldMode.prototype);

});

define("ace/mode/toml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/toml_highlight_rules","ace/mode/folding/ini"], function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var TomlHighlightRules = require("./toml_highlight_rules").TomlHighlightRules;
var FoldMode = require("./folding/ini").FoldMode;

var Mode = function() {
    this.HighlightRules = TomlHighlightRules;
    this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);

(function() {
    this.lineCommentStart = "#";
    this.$id = "ace/mode/toml";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>Update tmp/bower_components/ace-builds/src/mode-toml.js<commit_after><|endoftext|>


<commit_before>require('dotenv').config({silent: true})

var path = require('path')
var _ = require('lodash')
var environment = require('./environment.js').get()
var baseLine = {
  app: {
    name: 'Meangular'
  },
  minify: 'default',
  render: {
    cli: 'lodash', // __ or ejs or lodash.
    seo: 'lodash', // ejs or lodash. default is lodash
    lodash: {
      options: {} // https://lodash.com/docs#template
    },
    ejs: {
      options: {} // https://www.npmjs.com/package/ejs#options
    }
  },
  env: environment,
  // Root path of server
  root: path.join(__dirname, '/../../..'),
  // Server IP
  ip: process.env.IP || '0.0.0.0',
  hostname: process.env.HOST || process.env.HOSTNAME || 'localhost',
  // Enable Swagger.io at localhost:[port]/api/
  swagger: true,
  // Enable the use of babel for ES6
  babel: {
    options: {
      // NOTE you must install the proper package to use here
      presets: [
        'babel-preset-es2015'
      ],
      plugins: [
        'transform-class-properties'
      ]
    },
    folder: 'dist',
    active: false
  },
  // Plato
  plato: {
    title: 'meangular',
    eslint: {
      lastsemic: true,
      asi: true
    }
  },
  // JWT Object https://github.com/auth0/node-jsonwebtoken
  jwt: {
    // is used to compute a JWT SIGN
    secret: 'meangular',
    options: {
      expiresIn: 60 * 120 // 60 seconds * 120  = 2 hours
    }
  },
  // is used to compute a session hash
  sessionSecret: 'meangular',
  // The name of the MongoDB collection to store sessions in
  sessionCollection: 'sessions',
  // The session cookie settings
  sessionCookie: {
    path: '/',
    httpOnly: true,
    // If secure is set to true then it will cause the cookie to be set
    // only when SSL-enabled (HTTPS) is used, and otherwise it won't
    // set a cookie. 'true' is recommended yet it requires the above
    // mentioned pre-requisite.
    secure: false,
    // Only set the maxAge to null if the cookie shouldn't be expired
    // at all. The cookie will expunge when the browser is closed.
    maxAge: null
  },
  sessionName: 'session.id',
  // Supports MAX CDN
  maxcdn: {
    companyAlias: process.env.MAXCDN_COMPANY_ALIAS || '',
    consumerKey: process.env.MAXCDN_CONSUMER_KEY || '',
    consumerSecret: process.env.MAXCDN_CONSUMER_SECRET || ''
  },
  // SEO - Default html setup
  googleAnalytics: '',
  html: {
    title: 'Meangular',
    keywords: 'Meangular',
    description: 'Meangular',
    ogUrl: 'https://meangular.com/',
    ogType: 'website',
    ogTitle: 'Meangular',
    ogDescription: 'Meangular',
    ogImage: '',
    fbAppId: '',
    twitterCreator: '',
    twitterCard: '',
    twitterTitle: 'Meangular',
    twitterDescription: 'Meangular',
    twitterUrl: 'https://meangular.com/',
    twitterImage: '',
    twitterSite: '',
    canonical: 'https://meangular.com/',
    author: ''
  },
  seo: require('./seo.js'),
  // Assets disabled, will not be rendered to index page
  assets: {
    js: [
    ],
    css: [
    ]
  },
  bodyparser: {
    json: {limit: '100kb'},
    urlencoded: {limit: '100kb', extended: true}
  },
  helmet: {
    // https://github.com/helmetjs/helmet
  },
  expresValidator: {
    customValidators: {
      isArray: function (value) { // req.assert('param', 'Invalid Param').isArray()
        return _.isObject(value)
      },
      isObject: function (value) { // req.assert('param', 'Invalid Param').isObject()
        return _.isObject(value)
      },
      isString: function (value) { // req.assert('param', 'Invalid Param').isString()
        return _.isString(value)
      },
      isRegExp: function (value) { // req.assert('param', 'Invalid Param').isRegExp()
        return _.isRegExp(value)
      },
      isEmpty: function (value) { // req.assert('param', 'Invalid Param').isEmpty()
        return _.isEmpty(value)
      },
      gte: function (param, num) { // req.assert('param', 'Invalid Param').gte(5)
        return _.gte(param, num)
      },
      lte: function (param, num) { // req.assert('param', 'Invalid Param').lte(5)
        return _.lte(param, num)
      },
      gt: function (param, num) { // req.assert('param', 'Invalid Param').gt(5)
        return _.gt(param, num)
      },
      lt: function (param, num) { // req.assert('param', 'Invalid Param').lt(5)
        return _.lt(param, num)
      }
    },
    customSanitizers: {
      toArray: function (value) { // req.sanitize('postparam').toArray()
        return _.toArray(value)
      },
      toFinite: function (value) { // req.sanitize('postparam').toFinite()
        return _.toFinite(value)
      },
      toLength: function (value) { // req.sanitize('postparam').toLength()
        return _.toLength(value)
      },
      toPlainObject: function (value) { // req.sanitize('postparam').toPlainObject()
        return _.toPlainObject(value)
      },
      toString: function (value) { // req.sanitize('postparam').toString()
        return _.toString(value)
      }
    },
    errorFormatter: function (param, msg, value) {
      var namespace = param.split('.')
      var root = namespace.shift()
      var formParam = root

      while (namespace.length) {
        formParam += '[' + namespace.shift() + ']'
      }
      return {
        param: formParam,
        msg: msg,
        value: value
      }
    }
  },
  buildreq: {
    console: true,
    response: {
      method: 'get',
      data: {},
      user: {},
      count: 0,
      hostname: '',
      type: '',
      actions: {
        prev: false,
        next: false,
        reload: false
      },
      delete: ['error']
    },
    query: {
      sort: '',
      limit: 20,
      select: '',
      filter: {},
      populateId: 'user',
      populateItems: '',
      lean: false,
      skip: 0,
      where: '',
      gt: 1,
      lt: 0,
      in: [],
      equal: '',
      errorMessage: 'Unknown Value'
    },
    routing: {
      schema: true,
      url: '/api/v1/',
      build: true
    }
  },
  email: {
    templates: {
      welcome: {
        subject: 'Welcome to Meangular',
        text: function (username) {
          return 'Hi ' + username + ',\n\n' +
          'Thanks for signing up for Meangular.\n\n' +
          'If you have any questions about the site, you can reply to this ' +
          'email.\n\n' +
          '— Meangular'
        }
      },
      reset: {
        subject: 'Reset your password on Meangular ',
        text: function (email) {
          return 'Hello,\n\n' +
          'This is a confirmation that the password for your account ' + email + ' has just been changed.\n'
        }
      },
      forgot: {
        subject: 'Forgot your Meangular password?',
        text: function (host, token) {
          return 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + host + '/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
        }
      }
    },
    from: 'meangular@localhost.com',
    error: 'meangular@localhost.com',
    connect: {
      host: 'smtp.mandrillapp.com', // Gmail, SMTP
      port: '587',
      auth: {
        user: '',
        pass: ''
      }
    }
  }
}
if (environment === 'test') {
  baseLine = _.merge(baseLine, require('./environments/test.js'))
} else if (environment === 'production') {
  baseLine = _.merge(baseLine, require('./environments/production.js'))
} else if (environment === 'e2e') {
  baseLine = _.merge(baseLine, require('./environments/e2e.js'))
} else {
  baseLine = _.merge(baseLine, require('./environments/development.js'))
}

exports.get = function (env) {
  return baseLine
}
exports.set = function (identifer, value) {
  baseLine[identifer] = value
  return baseLine
}
<commit_msg>Update meta descriptions<commit_after>require('dotenv').config({silent: true})

var path = require('path')
var _ = require('lodash')
var environment = require('./environment.js').get()
var baseLine = {
  app: {
    name: 'Meangular'
  },
  minify: 'default',
  render: {
    cli: 'lodash', // __ or ejs or lodash.
    seo: 'lodash', // ejs or lodash. default is lodash
    lodash: {
      options: {} // https://lodash.com/docs#template
    },
    ejs: {
      options: {} // https://www.npmjs.com/package/ejs#options
    }
  },
  env: environment,
  // Root path of server
  root: path.join(__dirname, '/../../..'),
  // Server IP
  ip: process.env.IP || '0.0.0.0',
  hostname: process.env.HOST || process.env.HOSTNAME || 'localhost',
  // Enable Swagger.io at localhost:[port]/api/
  swagger: true,
  // Enable the use of babel for ES6
  babel: {
    options: {
      // NOTE you must install the proper package to use here
      presets: [
        'babel-preset-es2015'
      ],
      plugins: [
        'transform-class-properties'
      ]
    },
    folder: 'dist',
    active: false
  },
  // Plato
  plato: {
    title: 'meangular',
    eslint: {
      lastsemic: true,
      asi: true
    }
  },
  // JWT Object https://github.com/auth0/node-jsonwebtoken
  jwt: {
    // is used to compute a JWT SIGN
    secret: 'meangular',
    options: {
      expiresIn: 60 * 120 // 60 seconds * 120  = 2 hours
    }
  },
  // is used to compute a session hash
  sessionSecret: 'meangular',
  // The name of the MongoDB collection to store sessions in
  sessionCollection: 'sessions',
  // The session cookie settings
  sessionCookie: {
    path: '/',
    httpOnly: true,
    // If secure is set to true then it will cause the cookie to be set
    // only when SSL-enabled (HTTPS) is used, and otherwise it won't
    // set a cookie. 'true' is recommended yet it requires the above
    // mentioned pre-requisite.
    secure: false,
    // Only set the maxAge to null if the cookie shouldn't be expired
    // at all. The cookie will expunge when the browser is closed.
    maxAge: null
  },
  sessionName: 'session.id',
  // Supports MAX CDN
  maxcdn: {
    companyAlias: process.env.MAXCDN_COMPANY_ALIAS || '',
    consumerKey: process.env.MAXCDN_CONSUMER_KEY || '',
    consumerSecret: process.env.MAXCDN_CONSUMER_SECRET || ''
  },
  // SEO - Default html setup
  googleAnalytics: '',
  html: {
    title: 'Meangular',
    keywords: 'Meangular',
    description: 'Meangular is a full-stack Angular 4 solution based on Mean ' +
      'Stack JS using the Angular-cli. The aim is to provide a comfortable ' +
      'baseline for fully-featured, full-stack development. The front-end is ' +
      'functional enough as a beginning for most use cases without the need ' +
      'to remove custom styling or unneeded features.',
    ogUrl: 'https://meangular.com/',
    ogType: 'website',
    ogTitle: 'Meangular',
    ogDescription: 'Meangular is a full-stack Angular 4 solution based on Mean ' +
      'Stack JS using the Angular-cli. The aim is to provide a comfortable ' +
      'baseline for fully-featured, full-stack development. The front-end is ' +
      'functional enough as a beginning for most use cases without the need ' +
      'to remove custom styling or unneeded features.',
    ogImage: '',
    fbAppId: '',
    twitterCreator: '',
    twitterCard: '',
    twitterTitle: 'Meangular',
    twitterDescription: 'Meangular is a full-stack Angular 4 solution based on Mean ' +
      'Stack JS using the Angular-cli. The aim is to provide a comfortable ' +
      'baseline for fully-featured, full-stack development. The front-end is ' +
      'functional enough as a beginning for most use cases without the need ' +
      'to remove custom styling or unneeded features.',
    twitterUrl: 'https://meangular.com/',
    twitterImage: '',
    twitterSite: '',
    canonical: 'https://meangular.com/',
    author: ''
  },
  seo: require('./seo.js'),
  // Assets disabled, will not be rendered to index page
  assets: {
    js: [
    ],
    css: [
    ]
  },
  bodyparser: {
    json: {limit: '100kb'},
    urlencoded: {limit: '100kb', extended: true}
  },
  helmet: {
    // https://github.com/helmetjs/helmet
  },
  expresValidator: {
    customValidators: {
      isArray: function (value) { // req.assert('param', 'Invalid Param').isArray()
        return _.isObject(value)
      },
      isObject: function (value) { // req.assert('param', 'Invalid Param').isObject()
        return _.isObject(value)
      },
      isString: function (value) { // req.assert('param', 'Invalid Param').isString()
        return _.isString(value)
      },
      isRegExp: function (value) { // req.assert('param', 'Invalid Param').isRegExp()
        return _.isRegExp(value)
      },
      isEmpty: function (value) { // req.assert('param', 'Invalid Param').isEmpty()
        return _.isEmpty(value)
      },
      gte: function (param, num) { // req.assert('param', 'Invalid Param').gte(5)
        return _.gte(param, num)
      },
      lte: function (param, num) { // req.assert('param', 'Invalid Param').lte(5)
        return _.lte(param, num)
      },
      gt: function (param, num) { // req.assert('param', 'Invalid Param').gt(5)
        return _.gt(param, num)
      },
      lt: function (param, num) { // req.assert('param', 'Invalid Param').lt(5)
        return _.lt(param, num)
      }
    },
    customSanitizers: {
      toArray: function (value) { // req.sanitize('postparam').toArray()
        return _.toArray(value)
      },
      toFinite: function (value) { // req.sanitize('postparam').toFinite()
        return _.toFinite(value)
      },
      toLength: function (value) { // req.sanitize('postparam').toLength()
        return _.toLength(value)
      },
      toPlainObject: function (value) { // req.sanitize('postparam').toPlainObject()
        return _.toPlainObject(value)
      },
      toString: function (value) { // req.sanitize('postparam').toString()
        return _.toString(value)
      }
    },
    errorFormatter: function (param, msg, value) {
      var namespace = param.split('.')
      var root = namespace.shift()
      var formParam = root

      while (namespace.length) {
        formParam += '[' + namespace.shift() + ']'
      }
      return {
        param: formParam,
        msg: msg,
        value: value
      }
    }
  },
  buildreq: {
    console: true,
    response: {
      method: 'get',
      data: {},
      user: {},
      count: 0,
      hostname: '',
      type: '',
      actions: {
        prev: false,
        next: false,
        reload: false
      },
      delete: ['error']
    },
    query: {
      sort: '',
      limit: 20,
      select: '',
      filter: {},
      populateId: 'user',
      populateItems: '',
      lean: false,
      skip: 0,
      where: '',
      gt: 1,
      lt: 0,
      in: [],
      equal: '',
      errorMessage: 'Unknown Value'
    },
    routing: {
      schema: true,
      url: '/api/v1/',
      build: true
    }
  },
  email: {
    templates: {
      welcome: {
        subject: 'Welcome to Meangular',
        text: function (username) {
          return 'Hi ' + username + ',\n\n' +
          'Thanks for signing up for Meangular.\n\n' +
          'If you have any questions about the site, you can reply to this ' +
          'email.\n\n' +
          '— Meangular'
        }
      },
      reset: {
        subject: 'Reset your password on Meangular ',
        text: function (email) {
          return 'Hello,\n\n' +
          'This is a confirmation that the password for your account ' + email + ' has just been changed.\n'
        }
      },
      forgot: {
        subject: 'Forgot your Meangular password?',
        text: function (host, token) {
          return 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + host + '/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
        }
      }
    },
    from: 'meangular@localhost.com',
    error: 'meangular@localhost.com',
    connect: {
      host: 'smtp.mandrillapp.com', // Gmail, SMTP
      port: '587',
      auth: {
        user: '',
        pass: ''
      }
    }
  }
}
if (environment === 'test') {
  baseLine = _.merge(baseLine, require('./environments/test.js'))
} else if (environment === 'production') {
  baseLine = _.merge(baseLine, require('./environments/production.js'))
} else if (environment === 'e2e') {
  baseLine = _.merge(baseLine, require('./environments/e2e.js'))
} else {
  baseLine = _.merge(baseLine, require('./environments/development.js'))
}

exports.get = function (env) {
  return baseLine
}
exports.set = function (identifer, value) {
  baseLine[identifer] = value
  return baseLine
}
<|endoftext|>


<commit_before>'use strict';

/*==========================================
|                  UTIL                    |
|     Here you'll find useful functions    |
==========================================*/

/**
* Helper variables for room collision generation
*/
var tileWidth = 80;
var tileHeight = 72;
var maxTilesX = 24;
var maxTilesY = 15;

/**
* Collision objects to help streamline positioning them in a room
* This particular object is used to place an invisible collider on a wall
* @param {Number} width - width of the wall in tiles
* @param {Number} height - height of the wall in tiles
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {Number} xAnchor - value is used to set collision sprites anchor
* @param {Number} yAnchor - value is used to set collision sprites anchor
*/
function wallCollider (width, height, xPos, yPos, xAnchor, yAnchor)
{
var self = this;
self.width = width * tileWidth;
self.height = height * tileHeight;
self.x = xPos * tileWidth;
self.y = yPos * tileHeight;
self.anchorX = xAnchor;
self.anchorY = yAnchor;
self.image = 'test';
}

/**
* Collision objects to help streamline positioning them in a room
* the body size is based on the current collidable object's images
* new such images should follow similar dimensions
* Refer to /assets/maps/fieldObjects/smallCollidables for image sizes
* Object placed in position (0, 0) will be positioned in the bottom middle of the top leftmost visible tile
* Object at (maxTilesX, maxTilesY) will be placed outside of the room; 1 tile to the right and 1 tile under the room
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {String} image - the identifier of the image to use with the sprite; refer to load.js
*/
function smallCollisionSprite (xPos, yPos, image)
{
var self = this;
self.width = 94;
self.height = 145;
self.anchorX = 0.5;
self.anchorY = 1;
self.x = (xPos + 0.5) * tileWidth;
self.y = (yPos + 1) * tileHeight;
self.image = image;
self.bodyBoxLength = 58;
}

/**
* Collision objects to help streamline positioning them in a room
* the body size is based on the current collidable object's images
* new such images should follow similar dimensions
* Refer to /assets/maps/fieldObjects/largeCollidables for image sizes
* Object placed in position (0, 0) will be positioned in the bottom middle of the top leftmost visible tile
* Object at (maxTilesX, maxTilesY) will be placed (partially) outside of the room; 1 tile to the right and 1 tile under the room
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {String} image - the identifier of the image to use with the sprite; refer to load.js
*/
function largeCollisionSprite (xPos, yPos, image)
{
var self = this;
self.width = 280;
self.height = 286;
self.anchorX = 0.5;
self.anchorY = 1;
self.x = (xPos + 0.5) * tileWidth;
self.y = (yPos - 1) * tileHeight;
self.image = image;
self.bodyBoxLength = 156;
}

/**
* Get a point a minimum distance away from all players
* @param {game} game - The game object
* @param {Array} playerList - The list containing all player objects
* @param {Number} minimumDistance - The minimum distance from players to spawn from
* @param {Number} maxTryCount - The maximum amount of attempts until returning null
* @return {Point} A Point at least minimumDistance away from all players or null in which case no monster is spawned
*/
var getPosMinDPlayers = function (game, playerList, minimumDistance, maxTryCount)
	{
	var tryCount = 0;
	var currentBestDistance = 0;
	var currentBestPos = {};
	var acceptablePosition = false;
	var currentDistance = 0;
	while (!acceptablePosition || (tryCount < maxTryCount && maxTryCount != undefined))
		{
		var randomPos = {};
		randomPos.x = game.camera.x + game.rnd.integerInRange(0, game.camera.width);
		randomPos.y = game.camera.y + game.rnd.integerInRange(0, game.camera.height);
		currentDistance = dClosestPlayer(playerList, randomPos);
		if (currentDistance >= minimumDistance)
			{
			acceptablePosition = true;
			currentBestPos = randomPos;
			}
		else if(currentDistance >= currentBestDistance) {
			currentBestPos = randomPos;
		}
		tryCount++;
		}
		return currentBestPos;
	};

/**
* Get a initial spawn point
* @param {game} game - The game object
* @param {Array} playerList - The list containing all player objects
* @param {Number} minimumDistance - The minimum distance from players to spawn from
* @param {Number} maxTryCount - The maximum amount of attempts until returning null
* @return {Point} A Point where to spawn initially
*/
var getInitialSpawnPos = function (game, playerList, minimumDistance, borderLength, maxTryCount)
	{
	var tryCount = 0;
	var currentBestDistance = 0;
	var currentBestPos = {};
	var acceptablePosition = false;
	var currentDistance = 0;
	while (!acceptablePosition || (tryCount < maxTryCount && maxTryCount != undefined))
		{
		var randomPos = {};
		randomPos.x = game.camera.x + game.rnd.integerInRange(borderLength, game.camera.width - borderLength);
		randomPos.y = game.camera.y + game.rnd.integerInRange(borderLength, game.camera.height - borderLength);
		currentDistance = dClosestPlayer(playerList, randomPos);
		if (currentDistance >= minimumDistance)
			{
			acceptablePosition = true;
			currentBestPos = randomPos;
			}
		else if(currentDistance >= currentBestDistance) {
			currentBestPos = randomPos;
		}
		tryCount++;
		}
		return currentBestPos;
	};

/**
* Return the distance between the provided position and the closest player
* @param {Array} players - List of all players
* @param {Point} position - The position to which compare
* @return {Number} The distance in pixels from position to the closest player
*/
var dClosestPlayer = function (players, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	for (var id in players)
		{
		var player = players[id];
		if (player != undefined && !player.dead)
			{
			var distance = Math.sqrt( Math.pow( (player.sprite.position.x - position.x), 2 ) +
																Math.pow( (player.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				}
			}
		}
	return currentMin;
	};

/**
* Return the distance between the provided position and the closest enemy
* @param {Array} enemies - List of all enemies
* @param {Point} position - The position to which compare
* @return {Number} The distance in pixels from position to the closest enemy
*/
var dClosestEnemy = function (enemies, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	for (var i = 0; i < enemies.length; i++)
		{
		var enemy = enemies[i];
		if (!enemy.sprite.dead)
			{
			var distance = Math.sqrt( Math.pow( (enemy.sprite.position.x - position.x), 2 ) +
																Math.pow( (enemy.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				}
			}
		}
	return currentMin;
	};

/**
* Picks a random entry from a dictionary
* @param {Array} dict - The dictionary from which we pick an object
* @return {Object} A random object from the array
*/

var pickRandomFromDictionary = function (dict)
	{
	var keys = Object.keys(dict);
	var object
	object = dict[keys[ keys.length * Math.random() << 0]];
	return object;
	};

/**
* Return a player object closest to the given point or undefined if no player was found
* Used in some énemies when finding a new target
* @param {Array} players - The list of all player objects
* @param {Point} position - The point we need to find the closest player to
* @return {player} - The player object closest to a point
*/
	var getLivingPlayerClosestToPoint = function(players, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	var closestPlayer;
	var alivePlayers = getAllLivingFromDict(players);
	if(alivePlayers == undefined) return;
	for (var id in alivePlayers)
		{
		var player = alivePlayers[id];
		if (player != undefined)
			{
			var distance = Math.sqrt( Math.pow( (player.sprite.position.x - position.x), 2 ) +
																Math.pow( (player.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				closestPlayer = player;
				}
			}
		}
	return closestPlayer;
	};

/**
* Return a single random living object from a dictionary
* @param {Array} dict - The dictionary containing the objects from which to find the living objects from
* @return {Object} - List containing all living objects
*/
var getAliveFromObject = function(dict)
	{
	var aliveObject = [];
	var keys = Object.keys(dict);
	for(var i = 0; i < Object.keys(dict).length; i++)
		{
		if(!dict[keys[i]].dead)
			{
			aliveObject.push(dict[keys[i]]);
			}
		}
	var random = Math.floor(Math.random() * aliveObject.length);
	if(aliveObject.length > 0)
		{
		return aliveObject[random];
		}
	return;
	};

/**
* Return a list of living objects from a dictionary
* @param {Array} dict - The dictionary containing the objects from which to find the living objects from
* @return {Array} - List containing all living objects
*/
var getAllLivingFromObject = function(dict)
	{
	var livingObjects = [];
	var keys = Object.keys(dict);
	for(var i = 0; i < Object.keys(dict).length; i++)
		{
		if(!dict[keys[i]].dead)
			{
			livingObjects.push(dict[keys[i]]);
			}
		}
	if(livingObjects.length > 0)
		{
		return livingObjects;
		}
	return;
	};

/**
* Returns a list of players around the specified point
* @param {Array} players - List of all players.
* @param {Point} point - The point around which to check
* @param {Number} sizeX - The radius of the square in X direction which we use to check
* @param {Number} sizeY - The radius of the square in Y direction which we use to check
* @return {Array} List of all players within the specified area, or undefined if no players found in the area
*/
var getPlayersAroundPoint = function (players,point,sizeX,sizeY)
{
	//We use the data provided to construct a square around the area

	//Bottom left
	var squarePointsA = {}
	squarePointsA.x = point.x-sizeX;
	squarePointsA.y = point.y-sizeY;

	//Top right
	var squarePointsB = {}
	squarePointsB.x = point.x+sizeX;
	squarePointsB.y = point.y+sizeY;

	return getPlayersInArea(players,squarePointsA,squarePointsB);

}

/**
* Return a list of players inside the provided area defined by two points
* @param {Array} players - List of all players in the game
* @param {Point} botLeft - Represents the bottom left corner coordinates of the square
* @param {Point} topRight - Represents the top right corner coordinates of the square
* @return {Array} Array containing players inside the provided area or undefined if no players found in the area
*/
var getPlayersInArea = function (players, botLeft, topRight)
{
	var returnPlayers = [];
	var keys = Object.keys(players);
	var curPos;
	for(var i = 0; i < Object.keys(players).length; i++)
		{
			curPos = players[keys[i]].sprite.position;
			if(curPos.x > botLeft.x &&
				 curPos.y > botLeft.y &&
				 curPos.x < topRight.x &&
				 curPos.y < topRight.y)
			{
				returnPlayers.push(players[keys[i]]);
			}
		}
		if(returnPlayers.length > 0)
		{
			return returnPlayers;
		}
		return;
}

/**
* Return a random integer between min and max
* @param {Number} min - the lowest possible number to return
* @param {Number} min - the highest possible number to return
*/
var getRandomInt = function (min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	};

var getRandomPosition = function(border)
	{
	var position = {x: getRandomInt(game.camera.x + border, game.camera.x + game.width - border),
					y: getRandomInt(game.camera.y + border, game.camera.y + game.height - border)};
	return position;
	};

/**
* Resizes the game to fit new window dimensions
*/
var resizeGame = function ()
	{
	var height = window.innerHeight * window.devicePixelRatio;
	var width = window.innerWidth * window.devicePixelRatio;

	if (game != undefined)
		{
		game.width = width;
		game.height = height;
		game.stage.bounds.width = width;
		game.stage.bounds.height = height;

		if (game.renderType === 1)
			{
			game.renderer.resize(width, height);
			Phaser.Canvas.setSmoothingEnabled(game.context, false);
			}
		}
	};

/**
* Broadcasts a sound to all connected players, if screen has sound enabled, then only play audio on screen.
*/
var broadcastSound = function (players, soundIdentifier)
	{
	if (game.mute)
		{
		var ids = Object.keys(players);
		for (var i = 0; i < ids.length; i++)
			{
			gameClient.callClientRpc(ids[i], "playSound", [soundIdentifier], self, null);
			}
		} else if (game.state.states.play.roundManager != undefined)
		{
			game.state.states.play.roundManager.playSoundOnScreen(soundIdentifier);
		}
	};
<commit_msg>Update util.js<commit_after>'use strict';

/*==========================================
|                  UTIL                    |
|     Here you'll find useful functions    |
==========================================*/

/**
* Helper variables for room collision generation
*/
var tileWidth = 80;
var tileHeight = 72;
var maxTilesX = 24;
var maxTilesY = 15;

/**
* Collision objects to help streamline positioning them in a room
* This particular object is used to place an invisible collider on a wall
* @param {Number} width - width of the wall in tiles
* @param {Number} height - height of the wall in tiles
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {Number} xAnchor - value is used to set collision sprites anchor
* @param {Number} yAnchor - value is used to set collision sprites anchor
*/
function wallCollider (width, height, xPos, yPos, xAnchor, yAnchor)
{
var self = this;
self.width = width * tileWidth;
self.height = height * tileHeight;
self.x = xPos * tileWidth;
self.y = yPos * tileHeight;
self.anchorX = xAnchor;
self.anchorY = yAnchor;
self.image = 'empty';
}

/**
* Collision objects to help streamline positioning them in a room
* the body size is based on the current collidable object's images
* new such images should follow similar dimensions
* Refer to /assets/maps/fieldObjects/smallCollidables for image sizes
* Object placed in position (0, 0) will be positioned in the bottom middle of the top leftmost visible tile
* Object at (maxTilesX, maxTilesY) will be placed outside of the room; 1 tile to the right and 1 tile under the room
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {String} image - the identifier of the image to use with the sprite; refer to load.js
*/
function smallCollisionSprite (xPos, yPos, image)
{
var self = this;
self.width = 94;
self.height = 145;
self.anchorX = 0.5;
self.anchorY = 1;
self.x = (xPos + 0.5) * tileWidth;
self.y = (yPos + 1) * tileHeight;
self.image = image;
self.bodyBoxLength = 58;
}

/**
* Collision objects to help streamline positioning them in a room
* the body size is based on the current collidable object's images
* new such images should follow similar dimensions
* Refer to /assets/maps/fieldObjects/largeCollidables for image sizes
* Object placed in position (0, 0) will be positioned in the bottom middle of the top leftmost visible tile
* Object at (maxTilesX, maxTilesY) will be placed (partially) outside of the room; 1 tile to the right and 1 tile under the room
* @param {Number} xPos - x position based on tiles
* @param {Number} yPos - y position based on tiles
* @param {String} image - the identifier of the image to use with the sprite; refer to load.js
*/
function largeCollisionSprite (xPos, yPos, image)
{
var self = this;
self.width = 280;
self.height = 286;
self.anchorX = 0.5;
self.anchorY = 1;
self.x = (xPos + 0.5) * tileWidth;
self.y = (yPos - 1) * tileHeight;
self.image = image;
self.bodyBoxLength = 156;
}

/**
* Get a point a minimum distance away from all players
* @param {game} game - The game object
* @param {Array} playerList - The list containing all player objects
* @param {Number} minimumDistance - The minimum distance from players to spawn from
* @param {Number} maxTryCount - The maximum amount of attempts until returning null
* @return {Point} A Point at least minimumDistance away from all players or null in which case no monster is spawned
*/
var getPosMinDPlayers = function (game, playerList, minimumDistance, maxTryCount)
	{
	var tryCount = 0;
	var currentBestDistance = 0;
	var currentBestPos = {};
	var acceptablePosition = false;
	var currentDistance = 0;
	while (!acceptablePosition || (tryCount < maxTryCount && maxTryCount != undefined))
		{
		var randomPos = {};
		randomPos.x = game.camera.x + game.rnd.integerInRange(0, game.camera.width);
		randomPos.y = game.camera.y + game.rnd.integerInRange(0, game.camera.height);
		currentDistance = dClosestPlayer(playerList, randomPos);
		if (currentDistance >= minimumDistance)
			{
			acceptablePosition = true;
			currentBestPos = randomPos;
			}
		else if(currentDistance >= currentBestDistance) {
			currentBestPos = randomPos;
		}
		tryCount++;
		}
		return currentBestPos;
	};

/**
* Get a initial spawn point
* @param {game} game - The game object
* @param {Array} playerList - The list containing all player objects
* @param {Number} minimumDistance - The minimum distance from players to spawn from
* @param {Number} maxTryCount - The maximum amount of attempts until returning null
* @return {Point} A Point where to spawn initially
*/
var getInitialSpawnPos = function (game, playerList, minimumDistance, borderLength, maxTryCount)
	{
	var tryCount = 0;
	var currentBestDistance = 0;
	var currentBestPos = {};
	var acceptablePosition = false;
	var currentDistance = 0;
	while (!acceptablePosition || (tryCount < maxTryCount && maxTryCount != undefined))
		{
		var randomPos = {};
		randomPos.x = game.camera.x + game.rnd.integerInRange(borderLength, game.camera.width - borderLength);
		randomPos.y = game.camera.y + game.rnd.integerInRange(borderLength, game.camera.height - borderLength);
		currentDistance = dClosestPlayer(playerList, randomPos);
		if (currentDistance >= minimumDistance)
			{
			acceptablePosition = true;
			currentBestPos = randomPos;
			}
		else if(currentDistance >= currentBestDistance) {
			currentBestPos = randomPos;
		}
		tryCount++;
		}
		return currentBestPos;
	};

/**
* Return the distance between the provided position and the closest player
* @param {Array} players - List of all players
* @param {Point} position - The position to which compare
* @return {Number} The distance in pixels from position to the closest player
*/
var dClosestPlayer = function (players, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	for (var id in players)
		{
		var player = players[id];
		if (player != undefined && !player.dead)
			{
			var distance = Math.sqrt( Math.pow( (player.sprite.position.x - position.x), 2 ) +
																Math.pow( (player.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				}
			}
		}
	return currentMin;
	};

/**
* Return the distance between the provided position and the closest enemy
* @param {Array} enemies - List of all enemies
* @param {Point} position - The position to which compare
* @return {Number} The distance in pixels from position to the closest enemy
*/
var dClosestEnemy = function (enemies, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	for (var i = 0; i < enemies.length; i++)
		{
		var enemy = enemies[i];
		if (!enemy.sprite.dead)
			{
			var distance = Math.sqrt( Math.pow( (enemy.sprite.position.x - position.x), 2 ) +
																Math.pow( (enemy.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				}
			}
		}
	return currentMin;
	};

/**
* Picks a random entry from a dictionary
* @param {Array} dict - The dictionary from which we pick an object
* @return {Object} A random object from the array
*/

var pickRandomFromDictionary = function (dict)
	{
	var keys = Object.keys(dict);
	var object
	object = dict[keys[ keys.length * Math.random() << 0]];
	return object;
	};

/**
* Return a player object closest to the given point or undefined if no player was found
* Used in some énemies when finding a new target
* @param {Array} players - The list of all player objects
* @param {Point} position - The point we need to find the closest player to
* @return {player} - The player object closest to a point
*/
	var getLivingPlayerClosestToPoint = function(players, position)
	{
	var currentMin = 9999999; // Arbitrarily large number
	var closestPlayer;
	var alivePlayers = getAllLivingFromDict(players);
	if(alivePlayers == undefined) return;
	for (var id in alivePlayers)
		{
		var player = alivePlayers[id];
		if (player != undefined)
			{
			var distance = Math.sqrt( Math.pow( (player.sprite.position.x - position.x), 2 ) +
																Math.pow( (player.sprite.position.y - position.y), 2) );
			if (distance <= currentMin)
				{
				currentMin = distance;
				closestPlayer = player;
				}
			}
		}
	return closestPlayer;
	};

/**
* Return a single random living object from a dictionary
* @param {Array} dict - The dictionary containing the objects from which to find the living objects from
* @return {Object} - List containing all living objects
*/
var getAliveFromObject = function(dict)
	{
	var aliveObject = [];
	var keys = Object.keys(dict);
	for(var i = 0; i < Object.keys(dict).length; i++)
		{
		if(!dict[keys[i]].dead)
			{
			aliveObject.push(dict[keys[i]]);
			}
		}
	var random = Math.floor(Math.random() * aliveObject.length);
	if(aliveObject.length > 0)
		{
		return aliveObject[random];
		}
	return;
	};

/**
* Return a list of living objects from a dictionary
* @param {Array} dict - The dictionary containing the objects from which to find the living objects from
* @return {Array} - List containing all living objects
*/
var getAllLivingFromObject = function(dict)
	{
	var livingObjects = [];
	var keys = Object.keys(dict);
	for(var i = 0; i < Object.keys(dict).length; i++)
		{
		if(!dict[keys[i]].dead)
			{
			livingObjects.push(dict[keys[i]]);
			}
		}
	if(livingObjects.length > 0)
		{
		return livingObjects;
		}
	return;
	};

/**
* Returns a list of players around the specified point
* @param {Array} players - List of all players.
* @param {Point} point - The point around which to check
* @param {Number} sizeX - The radius of the square in X direction which we use to check
* @param {Number} sizeY - The radius of the square in Y direction which we use to check
* @return {Array} List of all players within the specified area, or undefined if no players found in the area
*/
var getPlayersAroundPoint = function (players,point,sizeX,sizeY)
{
	//We use the data provided to construct a square around the area

	//Bottom left
	var squarePointsA = {}
	squarePointsA.x = point.x-sizeX;
	squarePointsA.y = point.y-sizeY;

	//Top right
	var squarePointsB = {}
	squarePointsB.x = point.x+sizeX;
	squarePointsB.y = point.y+sizeY;

	return getPlayersInArea(players,squarePointsA,squarePointsB);

}

/**
* Return a list of players inside the provided area defined by two points
* @param {Array} players - List of all players in the game
* @param {Point} botLeft - Represents the bottom left corner coordinates of the square
* @param {Point} topRight - Represents the top right corner coordinates of the square
* @return {Array} Array containing players inside the provided area or undefined if no players found in the area
*/
var getPlayersInArea = function (players, botLeft, topRight)
{
	var returnPlayers = [];
	var keys = Object.keys(players);
	var curPos;
	for(var i = 0; i < Object.keys(players).length; i++)
		{
			curPos = players[keys[i]].sprite.position;
			if(curPos.x > botLeft.x &&
				 curPos.y > botLeft.y &&
				 curPos.x < topRight.x &&
				 curPos.y < topRight.y)
			{
				returnPlayers.push(players[keys[i]]);
			}
		}
		if(returnPlayers.length > 0)
		{
			return returnPlayers;
		}
		return;
}

/**
* Return a random integer between min and max
* @param {Number} min - the lowest possible number to return
* @param {Number} min - the highest possible number to return
*/
var getRandomInt = function (min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	};

var getRandomPosition = function(border)
	{
	var position = {x: getRandomInt(game.camera.x + border, game.camera.x + game.width - border),
					y: getRandomInt(game.camera.y + border, game.camera.y + game.height - border)};
	return position;
	};

/**
* Resizes the game to fit new window dimensions
*/
var resizeGame = function ()
	{
	var height = window.innerHeight * window.devicePixelRatio;
	var width = window.innerWidth * window.devicePixelRatio;

	if (game != undefined)
		{
		game.width = width;
		game.height = height;
		game.stage.bounds.width = width;
		game.stage.bounds.height = height;

		if (game.renderType === 1)
			{
			game.renderer.resize(width, height);
			Phaser.Canvas.setSmoothingEnabled(game.context, false);
			}
		}
	};

/**
* Broadcasts a sound to all connected players, if screen has sound enabled, then only play audio on screen.
*/
var broadcastSound = function (players, soundIdentifier)
	{
	if (game.mute)
		{
		var ids = Object.keys(players);
		for (var i = 0; i < ids.length; i++)
			{
			gameClient.callClientRpc(ids[i], "playSound", [soundIdentifier], self, null);
			}
		} else if (game.state.states.play.roundManager != undefined)
		{
			game.state.states.play.roundManager.playSoundOnScreen(soundIdentifier);
		}
	};
<|endoftext|>


<commit_before>'use strict'

var request = require('request')
  , cheerio = require('cheerio')
  , Promise = require('bluebird')
  , Nightmare = require('nightmare')
  , RateLimiter = require('limiter').RateLimiter
  , EventEmitter = require('events')
  , util = require('util');

function Scraper () {
	EventEmitter.call(this);
}

util.inherits(Scraper, EventEmitter);

/**
 * Get the image src for images, options specify the details.
 */
Scraper.prototype.list = function (options) {
	var self = this;

	if (!options || !options.keyword) return Promise.reject(new Error('no keyword provided'));

	this.keyword = options.keyword;
	this.rlimit = new RateLimiter(options.rlimit || 0, 'second');
	this.userAgent = options.userAgent || 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36';
	this.noptions = options.nightmare || {};
	this.timeout = options.timeout || 10000;
	this.advanced = options.advanced;

	return self._links().then(function (res) {
		if (options.num) {
			res = res.slice(0, options.num);
		}

		res.filter(function (r) {
			return r !== null;
		});

		self.emit('end', res);

		return res;
	});
}

/**
 * Returns a complete list of all the image details.
 */
Scraper.prototype._links = function () {
	var self = this;
	var search_base = 'https://www.google.com/search?q=%&source=lnms&tbm=isch&sa=X';
	if (this.advanced) {
		var base = '&tbs=';
		var build = [];
		if (this.advanced.resolution) {
			build.push('isz:'+this.advanced.resolution);
		}
		if (this.advanced.imgType) {
			build.push('itp:'+this.advanced.imgType);
		}

		build = build.length > 1 ? build.join(',') : build[0];
		search_base += '&tbs='+build;
	}
	return new Promise.resolve(
		new Nightmare(self.noptions)
			.useragent(self.userAgent)
			.goto(search_base.replace('%', encodeURIComponent(self.keyword)))
			.wait()
			.inject('js', __dirname + '/jquery-2.1.4.min.js')

			.evaluate(function (timeout) {
				$.data(document, 'timeout', false);
				setTimeout(function () {
					$.data(document, 'timeout', true);
				}, timeout);

				setInterval(function() {
					$('html, body').animate({ scrollTop: $(document).height() }, 1000);

					var button = $('.ksb._kvc');	// try to load more
					if (button) {
						$.data(document, 'finished', false);
						button.click();
					}
				}, 1000);

				// catch all AJAX events such that we can determine when we are finished
				var oldSend = XMLHttpRequest.prototype.send;
				XMLHttpRequest.prototype.send = function () {
					var oldOnReady = this.onreadystatechange;
					this.onreadystatechange = function () {
						oldOnReady.call(this);
						if (this.readyState === XMLHttpRequest.DONE)
							$.data(document, 'finished', true);
					}
					oldSend.apply(this, arguments);
				}
			}, self.timeout)
			.wait(function () {
				return (($(window).scrollTop() + $(window).height() == $(document).height()) &&
						!$('.ksb._kvc').is(':visible') &&
						$.data(document, 'finished')) || $.data(document, 'timeout');
			})

			.on('console', function(type, msg) {
				console.log('msg ' + msg);
			})

			.evaluate(function () {
				// get all the src's
				var results = [];
				$('.rg_l').each(function () {
					var meta = JSON.parse($(this).parent().find('.rg_meta').text());

					console.log(JSON.stringify(meta));

					var item = {
						type: 'image/' + meta.ity,
						width: meta.ow,
						height: meta.oh,
						// size: meta.os.match(/[-+]?(\d*[.])?\d+/)[0], // fails query as property no longer exists
						url: meta.ou,
						thumb_url: meta.tu,
						thumb_width: meta.tw,
						thumb_height: meta.th
						// unit: meta.os.match(/\D+/).slice(-1)[0] // fails query as property no longer exists
					};

					results.push(item);
				});
				return results;
			}).end()
	);
}

module.exports = Scraper;<commit_msg>removed console log statements<commit_after>'use strict'

var request = require('request')
  , cheerio = require('cheerio')
  , Promise = require('bluebird')
  , Nightmare = require('nightmare')
  , RateLimiter = require('limiter').RateLimiter
  , EventEmitter = require('events')
  , util = require('util');

function Scraper () {
	EventEmitter.call(this);
}

util.inherits(Scraper, EventEmitter);

/**
 * Get the image src for images, options specify the details.
 */
Scraper.prototype.list = function (options) {
	var self = this;

	if (!options || !options.keyword) return Promise.reject(new Error('no keyword provided'));

	this.keyword = options.keyword;
	this.rlimit = new RateLimiter(options.rlimit || 0, 'second');
	this.userAgent = options.userAgent || 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36';
	this.noptions = options.nightmare || {};
	this.timeout = options.timeout || 10000;
	this.advanced = options.advanced;

	return self._links().then(function (res) {
		if (options.num) {
			res = res.slice(0, options.num);
		}

		res.filter(function (r) {
			return r !== null;
		});

		self.emit('end', res);

		return res;
	});
}

/**
 * Returns a complete list of all the image details.
 */
Scraper.prototype._links = function () {
	var self = this;
	var search_base = 'https://www.google.com/search?q=%&source=lnms&tbm=isch&sa=X';
	if (this.advanced) {
		var base = '&tbs=';
		var build = [];
		if (this.advanced.resolution) {
			build.push('isz:'+this.advanced.resolution);
		}
		if (this.advanced.imgType) {
			build.push('itp:'+this.advanced.imgType);
		}

		build = build.length > 1 ? build.join(',') : build[0];
		search_base += '&tbs='+build;
	}
	return new Promise.resolve(
		new Nightmare(self.noptions)
			.useragent(self.userAgent)
			.goto(search_base.replace('%', encodeURIComponent(self.keyword)))
			.wait()
			.inject('js', __dirname + '/jquery-2.1.4.min.js')

			.evaluate(function (timeout) {
				$.data(document, 'timeout', false);
				setTimeout(function () {
					$.data(document, 'timeout', true);
				}, timeout);

				setInterval(function() {
					$('html, body').animate({ scrollTop: $(document).height() }, 1000);

					var button = $('.ksb._kvc');	// try to load more
					if (button) {
						$.data(document, 'finished', false);
						button.click();
					}
				}, 1000);

				// catch all AJAX events such that we can determine when we are finished
				var oldSend = XMLHttpRequest.prototype.send;
				XMLHttpRequest.prototype.send = function () {
					var oldOnReady = this.onreadystatechange;
					this.onreadystatechange = function () {
						oldOnReady.call(this);
						if (this.readyState === XMLHttpRequest.DONE)
							$.data(document, 'finished', true);
					}
					oldSend.apply(this, arguments);
				}
			}, self.timeout)
			.wait(function () {
				return (($(window).scrollTop() + $(window).height() == $(document).height()) &&
						!$('.ksb._kvc').is(':visible') &&
						$.data(document, 'finished')) || $.data(document, 'timeout');
			})

			.evaluate(function () {
				// get all the src's
				var results = [];
				$('.rg_l').each(function () {
					var meta = JSON.parse($(this).parent().find('.rg_meta').text());

					var item = {
						type: 'image/' + meta.ity,
						width: meta.ow,
						height: meta.oh,
						// size: meta.os.match(/[-+]?(\d*[.])?\d+/)[0], // fails query as property no longer exists
						url: meta.ou,
						thumb_url: meta.tu,
						thumb_width: meta.tw,
						thumb_height: meta.th
						// unit: meta.os.match(/\D+/).slice(-1)[0] // fails query as property no longer exists
					};

					results.push(item);
				});
				return results;
			}).end()
	);
}

module.exports = Scraper;
<|endoftext|>


<commit_before>export const Symbols = {
  ARGUMENTS: Symbol('arguments'),
};

export default function astToBody(ast) {
  const fieldNodes = ast.fieldNodes;

  const body = extractSelectionSet(ast.fieldNodes[0].selectionSet);

  return body;
}

function extractSelectionSet(set) {
  let body = {};
  set.selections.forEach(el => {
    if (!el.selectionSet) {
      body[el.name.value] = 1;
    } else {
      body[el.name.value] = extractSelectionSet(el.selectionSet);
      if (el.arguments.length) {
        let argumentMap = {};
        el.arguments.forEach(arg => {
          argumentMap[arg.name.value] = arg.value.value;
        });

        body[el.name.value][Symbols.ARGUMENTS] = argumentMap;
      }
    }
  });

  return body;
}
<commit_msg>fix: add support for input types<commit_after>export const Symbols = {
  ARGUMENTS: Symbol('arguments'),
};

export default function astToBody(ast) {
  const fieldNodes = ast.fieldNodes;

  const body = extractSelectionSet(ast.fieldNodes[0].selectionSet);

  return body;
}

function extractSelectionSet(set) {
  let body = {};
  set.selections.forEach(el => {
    if (!el.selectionSet) {
      body[el.name.value] = 1;
    } else {
      body[el.name.value] = extractSelectionSet(el.selectionSet);
      if (el.arguments.length) {
        let argumentMap = {};
        el.arguments.forEach(arg => {
          if (arg.value.kind === "ObjectValue") {
            argumentMap[arg.name.value] = arg.value.fields.reduce((acc, field) => {
              acc[field.name.value] = field.value.value;
              return acc;
            }, {});
          } else {
            argumentMap[arg.name.value] = arg.value.value;
          }
        });

        body[el.name.value][Symbols.ARGUMENTS] = argumentMap;
      }
    }
  });

  return body;
}
<|endoftext|>


<commit_before>// svg-injector.js 1.0.1
//
// Copyright (c) 2014 Waybury <hello@waybury.com>
// SVGInjector may be freely distributed under the MIT license.
//
// For full details and documentation:
// https://github.com/iconic/SVGInjector

(function (window, document) {

  'use strict';

  // Environment
  var isLocal = window.location.protocol === 'file:';
  var hasSvgSupport = document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1');

  // SVG Cache
  var svgCache = {};

  var injectCount = 0;

  // Request Queue
  var requestQueue = [];

  // Script running status
  var ranScripts = {};

  var cloneSvg = function (sourceSvg) {
    return sourceSvg.cloneNode(true);
  };

  var queueRequest = function (url, callback) {
    requestQueue[url] = requestQueue[url] || [];
    requestQueue[url].push(callback);
  };

  var processRequestQueue = function (url) {
    for (var i = 0, len = requestQueue[url].length; i < len; i++) {
      // Make these calls async so we avoid blocking the page/renderer
      /* jshint loopfunc: true */
      (function (index) {
        setTimeout(function () {
          requestQueue[url][index](cloneSvg(svgCache[url]));
        }, 0);
      })(i);
      /* jshint loopfunc: false */
    }
  };

  var loadSvg = function (url, callback) {
    if (svgCache[url] !== undefined) {
      if (svgCache[url] instanceof SVGSVGElement) {
        // We already have it in cache, so use it
        callback(svgCache[url].cloneNode(true));
      }
      else {
        // We don't have it in cache yet, but we are loading it, so queue this request
        queueRequest(url, callback);
      }
    }
    else {

      if (!window.XMLHttpRequest) {
        callback('Browser does not support XMLHttpRequest');
        return false;
      }

      // Seed the cache to indicate we are loading this URL already
      svgCache[url] = {};
      queueRequest(url, callback);

      var httpRequest = new XMLHttpRequest();

      httpRequest.onreadystatechange = function () {
        // readyState 4 = complete
        if (httpRequest.readyState === 4) {

          // Handle status
          if (httpRequest.status === 404 || httpRequest.responseXML === null) {
            callback('Unable to load SVG file: ' + url);

            if (isLocal) callback('Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver.');

            callback();
            return false;
          }

          // 200 success from server, or 0 when using file:// protocol locally
          if (httpRequest.status === 200 || (isLocal && httpRequest.status === 0)) {

            /* globals Document */
            if (httpRequest.responseXML instanceof Document) {
              // Cache it
              svgCache[url] = httpRequest.responseXML.documentElement;
            }
            /* globals -Document */

            // IE9 doesn't create a responseXML Document object from loaded SVG,
            // and throws a "DOM Exception: HIERARCHY_REQUEST_ERR (3)" error when injected.
            //
            // So, we'll just create our own manually via the DOMParser using
            // the the raw XML responseText.
            //
            // :NOTE: IE8 and older doesn't have DOMParser, but they can't do SVG either, so...
            else if (DOMParser && (DOMParser instanceof Function)) {
              var xmlDoc;
              try {
                var parser = new DOMParser();
                xmlDoc = parser.parseFromString(httpRequest.responseText, 'text/xml');
              }
              catch (e) {
                xmlDoc = undefined;
              }

              if (!xmlDoc || xmlDoc.getElementsByTagName('parsererror').length) {
                callback('Unable to parse SVG file: ' + url);
                return false;
              }
              else {
                // Cache it
                svgCache[url] = xmlDoc.documentElement;
              }
            }

            // We've loaded a new asset, so process any requests waiting for it
            processRequestQueue(url);
          }
          else {
            callback('There was a problem injecting the SVG: ' + httpRequest.status + ' ' + httpRequest.statusText);
            return false;
          }
        }
      };

      httpRequest.open('GET', url);

      // Treat and parse the response as XML, even if the
      // server sends us a different mimetype
      if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/xml');

      httpRequest.send();
    }
  };

  // Inject a single element
  var injectElement = function (el, evalScripts, pngFallback, callback) {

    // Grab the src or data-src attribute
    var imgUrl = el.getAttribute('data-src') || el.getAttribute('src');

    // We can only inject SVG
    if (!(/svg$/i).test(imgUrl)) {
      callback('Attempted to inject a file with a non-svg extension: ' + imgUrl);
      return;
    }

    // If we don't have SVG support try to fall back to png
    if (!hasSvgSupport) {
      if (pngFallback) {
        el.setAttribute('src', pngFallback + '/' + imgUrl.split('/').pop().replace('.svg', '.png'));
        callback(null);
      }
      else {
        callback('This browser does not support SVG and no PNG fallback was defined.');
      }

      return;
    }

    // Try to avoid loading the orginal image src if possible.
    el.setAttribute('src', '');

    // Load it up
    loadSvg(imgUrl, function (svg) {

      if (svg === undefined || typeof svg === 'string') {
        callback(svg);
        return false;
      }

      var imgId = el.getAttribute('id');
      if (imgId) {
        svg.setAttribute('id', imgId);
      }

      var imgTitle = el.getAttribute('title');
      if (imgTitle) {
        svg.setAttribute('title', imgTitle);
      }

      var imgClass = el.getAttribute('class');
      if (imgClass) {
        // :TODO: don't add dups
        var classMerge = [svg.getAttribute('class'), 'iconic-injected-svg', imgClass].join(' ');
        svg.setAttribute('class', classMerge);
      }

      var imgStyle = el.getAttribute('style');
      if (imgStyle) {
        svg.setAttribute('style', imgStyle);
      }

      // Copy all the data elements to the svg
      var imgData = [].filter.call(el.attributes, function (at) {
        return (/^data-\w[\w\-]*$/).test(at.name);
      });
      Array.prototype.forEach.call(imgData, function (dataAttr) {
        if (dataAttr.name && dataAttr.value) {
          svg.setAttribute(dataAttr.name, dataAttr.value);
        }
      });

      // Make sure any internally referenced clipPath ids and their
      // clip-path references are unique.
      //
      // This addresses the issue of having multiple instances of the
      // same SVG on a page and only the first clipPath id is referenced.
      //
      // Browsers often shortcut the SVG Spec and don't use clipPaths
      // contained in parent elements that are hidden, so if you hide the first
      // SVG instance on the page, then all other instances lose their clipping.
      // Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=376027
      var clipPaths = svg.querySelectorAll('defs clipPath[id]');
      var newClipPathName;
      for (var i = 0, clipPathsLen = clipPaths.length; i < clipPathsLen; i++) {
        newClipPathName = clipPaths[i].id + '-' + injectCount;
        // :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
        var usingClipPath = svg.querySelectorAll('[clip-path*="' + clipPaths[i].id + '"]');
        for (var j = 0, usingClipPathLen = usingClipPath.length; j < usingClipPathLen; j++) {
          usingClipPath[j].setAttribute('clip-path', 'url(#' + newClipPathName + ')');
        }
        clipPaths[i].id = newClipPathName;
      }

      // Remove any unwanted/invalid namespaces that might have been added by SVG editing tools
      svg.removeAttribute('xmlns:a');

      // Post page load injected SVGs don't automatically have their script
      // elements run, so we'll need to make that happen, if requested

      // Find then prune the scripts
      var scripts = svg.querySelectorAll('script');
      var scriptsToEval = [];
      var script, scriptType;

      for (var k = 0, scriptsLen = scripts.length; k < scriptsLen; k++) {
        scriptType = scripts[k].getAttribute('type');

        // Only process javascript types.
        // SVG defaults to 'application/ecmascript' for unset types
        if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {

          // innerText for IE, textContent for other browsers
          script = scripts[k].innerText || scripts[k].textContent;

          // Stash
          scriptsToEval.push(script);

          // Tidy up and remove the script element since we don't need it anymore
          svg.removeChild(scripts[k]);
        }
      }

      // Run/Eval the scripts if needed
      if (scriptsToEval.length > 0 && (evalScripts === 'always' || (evalScripts === 'once' && !ranScripts[imgUrl]))) {
        for (var l = 0, scriptsToEvalLen = scriptsToEval.length; l < scriptsToEvalLen; l++) {

          // :NOTE: Yup, this is a form of eval, but it is being used to eval code
          // the caller has explictely asked to be loaded, and the code is in a caller
          // defined SVG file... not raw user input.
          //
          // Also, the code is evaluated in a closure and not in the global scope.
          // If you need to put something in global scope, use 'window'
          new Function(scriptsToEval[l])(window); // jshint ignore:line
        }

        // Remember we already ran scripts for this svg
        ranScripts[imgUrl] = true;
      }

      // Replace the image with the svg
      el.parentNode.replaceChild(svg, el);

      // Increment the injected count
      injectCount++;

      callback(svg);
    });
  };

  /**
   * Array.forEach() polyfill for <= IE8
   * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
   */
  if (!Array.prototype.forEach) {
    Array.prototype.forEach = function (fn, scope) {
      if (this === void 0 || this === null || typeof fn !== 'function') {
        throw new TypeError();
      }

      /* jshint bitwise: false */
      var i, len = this.length >>> 0;
      /* jshint bitwise: true */

      for (i = 0; i < len; ++i) {
        if (i in this) {
          fn.call(scope, this[i], i, this);
        }
      }
    };
  }

  /**
   * SVGInjector
   *
   * Replace the given elements with their full inline SVG DOM elements.
   *
   * :NOTE: We are using get/setAttribute with SVG because the SVG DOM spec differs from HTML DOM and
   * can return other unexpected object types when trying to directly access svg properties.
   * ex: "className" returns a SVGAnimatedString with the class value found in the "baseVal" property,
   * instead of simple string like with HTML Elements.
   *
   * @param {mixes} Array of or single DOM element
   * @param {object} options
   * @param {function} callback
   * @return {object} Instance of SVGInjector
   */
  var SVGInjector = function (elements, options, done) {

    // Options & defaults
    options = options || {};

    // Should we run the scripts blocks found in the SVG
    // 'always' - Run them every time
    // 'once' - Only run scripts once for each SVG
    // [false|'never'] - Ignore scripts
    var evalScripts = options.evalScripts || 'always';

    // Location of fallback pngs, if desired
    var pngFallback = options.pngFallback || false;

    // Callback to run during each SVG injection, returning the SVG injected
    var eachCallback = options.each;

    // Do the injection...
    if (elements.length !== undefined) {
      var elementsLoaded = 0;
      Array.prototype.forEach.call(elements, function (element) {
        injectElement(element, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof (eachCallback) === 'function') eachCallback(svg);
          if (done && elements.length === ++elementsLoaded) done(elementsLoaded);
        });
      });
    }
    else {
      if (elements !== null) {
        injectElement(elements, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof (eachCallback) === 'function') eachCallback(svg);
          if (done) done(1);
        });
      }
      else {
        if (done) done(0);
      }
    }
  };

  /* global module, exports: true, define */
  // Node.js or CommonJS
  if (typeof module === 'object' && typeof module.exports === 'object') {
    module.exports = exports = SVGInjector;
  }
  // AMD support
  else if (typeof define === 'function' && define.amd) {
    define(function () {
      return SVGInjector;
    });
  }
  // Otherwise, attach to window as global
  else if (typeof window === 'object') {
    window.SVGInjector = SVGInjector;
  }
  /* global -module, -exports, -define */

}(window, document));
<commit_msg>small cleanup<commit_after>// svg-injector.js 1.0.1
//
// Copyright (c) 2014 Waybury <hello@waybury.com>
// SVGInjector may be freely distributed under the MIT license.
//
// For full details and documentation:
// https://github.com/iconic/SVGInjector

(function (window, document) {

  'use strict';

  // Environment
  var isLocal = window.location.protocol === 'file:';
  var hasSvgSupport = document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1');

  function isFunction(value) {
    return typeof value === 'function';
  }

  function isDefined(value){
    return typeof value !== 'undefined';
  }

  // SVG Cache
  var svgCache = {};

  var injectCount = 0;

  // Request Queue
  var requestQueue = [];

  // Script running status
  var ranScripts = {};

  var cloneSvg = function (sourceSvg) {
    return sourceSvg.cloneNode(true);
  };

  var queueRequest = function (url, callback) {
    requestQueue[url] = requestQueue[url] || [];
    requestQueue[url].push(callback);
  };

  var processRequestQueue = function (url) {
    for (var i = 0, len = requestQueue[url].length; i < len; i++) {
      // Make these calls async so we avoid blocking the page/renderer
      /* jshint loopfunc: true */
      (function (index) {
        setTimeout(function () {
          requestQueue[url][index](cloneSvg(svgCache[url]));
        }, 0);
      })(i);
      /* jshint loopfunc: false */
    }
  };

  var loadSvg = function (url, callback) {
    if (isDefined(svgCache[url])) {
      if (svgCache[url] instanceof SVGSVGElement) {
        // We already have it in cache, so use it
        callback(cloneSvg(svgCache[url]));
      }
      else {
        // We don't have it in cache yet, but we are loading it, so queue this request
        queueRequest(url, callback);
      }
    }
    else {

      if (!window.XMLHttpRequest) {
        callback('Browser does not support XMLHttpRequest');
        return false;
      }

      // Seed the cache to indicate we are loading this URL already
      svgCache[url] = {};
      queueRequest(url, callback);

      var httpRequest = new XMLHttpRequest();

      httpRequest.onreadystatechange = function () {
        // readyState 4 = complete
        if (httpRequest.readyState === 4) {

          // Handle status
          if (httpRequest.status === 404 || httpRequest.responseXML === null) {
            callback('Unable to load SVG file: ' + url);

            if (isLocal) callback('Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver.');

            callback();
            return false;
          }

          // 200 success from server, or 0 when using file:// protocol locally
          if (httpRequest.status === 200 || (isLocal && httpRequest.status === 0)) {

            /* globals Document */
            if (httpRequest.responseXML instanceof Document) {
              // Cache it
              svgCache[url] = httpRequest.responseXML.documentElement;
            }
            /* globals -Document */

            // IE9 doesn't create a responseXML Document object from loaded SVG,
            // and throws a "DOM Exception: HIERARCHY_REQUEST_ERR (3)" error when injected.
            //
            // So, we'll just create our own manually via the DOMParser using
            // the the raw XML responseText.
            //
            // :NOTE: IE8 and older doesn't have DOMParser, but they can't do SVG either, so...
            else if (DOMParser && (DOMParser instanceof Function)) {
              var xmlDoc;
              try {
                var parser = new DOMParser();
                xmlDoc = parser.parseFromString(httpRequest.responseText, 'text/xml');
              }
              catch (e) {
                xmlDoc = undefined;
              }

              if (!xmlDoc || xmlDoc.getElementsByTagName('parsererror').length) {
                callback('Unable to parse SVG file: ' + url);
                return false;
              }
              else {
                // Cache it
                svgCache[url] = xmlDoc.documentElement;
              }
            }

            // We've loaded a new asset, so process any requests waiting for it
            processRequestQueue(url);
          }
          else {
            callback('There was a problem injecting the SVG: ' + httpRequest.status + ' ' + httpRequest.statusText);
            return false;
          }
        }
      };

      httpRequest.open('GET', url);

      // Treat and parse the response as XML, even if the
      // server sends us a different mimetype
      if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/xml');

      httpRequest.send();
    }
  };

  // Inject a single element
  var injectElement = function (el, evalScripts, pngFallback, callback) {

    // Grab the src or data-src attribute
    var imgUrl = el.getAttribute('data-src') || el.getAttribute('src');

    // We can only inject SVG
    if (!(/svg$/i).test(imgUrl)) {
      callback('Attempted to inject a file with a non-svg extension: ' + imgUrl);
      return;
    }

    // If we don't have SVG support try to fall back to png
    if (!hasSvgSupport) {
      if (pngFallback) {
        el.setAttribute('src', pngFallback + '/' + imgUrl.split('/').pop().replace('.svg', '.png'));
        callback(null);
      }
      else {
        callback('This browser does not support SVG and no PNG fallback was defined.');
      }

      return;
    }

    // Try to avoid loading the orginal image src if possible.
    el.setAttribute('src', '');

    // Load it up
    loadSvg(imgUrl, function (svg) {

      if (!isDefined(svg) || typeof svg === 'string') {
        callback(svg);
        return false;
      }

      var imgId = el.getAttribute('id');
      if (imgId) {
        svg.setAttribute('id', imgId);
      }

      var imgTitle = el.getAttribute('title');
      if (imgTitle) {
        svg.setAttribute('title', imgTitle);
      }

      var imgClass = el.getAttribute('class');
      if (imgClass) {
        // :TODO: don't add dups
        var classMerge = [svg.getAttribute('class'), 'iconic-injected-svg', imgClass].join(' ');
        svg.setAttribute('class', classMerge);
      }

      var imgStyle = el.getAttribute('style');
      if (imgStyle) {
        svg.setAttribute('style', imgStyle);
      }

      // Copy all the data elements to the svg
      var imgData = [].filter.call(el.attributes, function (at) {
        return (/^data-\w[\w\-]*$/).test(at.name);
      });
      Array.prototype.forEach.call(imgData, function (dataAttr) {
        if (dataAttr.name && dataAttr.value) {
          svg.setAttribute(dataAttr.name, dataAttr.value);
        }
      });

      // Make sure any internally referenced clipPath ids and their
      // clip-path references are unique.
      //
      // This addresses the issue of having multiple instances of the
      // same SVG on a page and only the first clipPath id is referenced.
      //
      // Browsers often shortcut the SVG Spec and don't use clipPaths
      // contained in parent elements that are hidden, so if you hide the first
      // SVG instance on the page, then all other instances lose their clipping.
      // Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=376027
      var clipPaths = svg.querySelectorAll('defs clipPath[id]');
      var newClipPathName;
      for (var i = 0, clipPathsLen = clipPaths.length; i < clipPathsLen; i++) {
        newClipPathName = clipPaths[i].id + '-' + injectCount;
        // :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
        var usingClipPath = svg.querySelectorAll('[clip-path*="' + clipPaths[i].id + '"]');
        for (var j = 0, usingClipPathLen = usingClipPath.length; j < usingClipPathLen; j++) {
          usingClipPath[j].setAttribute('clip-path', 'url(#' + newClipPathName + ')');
        }
        clipPaths[i].id = newClipPathName;
      }

      // Remove any unwanted/invalid namespaces that might have been added by SVG editing tools
      svg.removeAttribute('xmlns:a');

      // Post page load injected SVGs don't automatically have their script
      // elements run, so we'll need to make that happen, if requested

      // Find then prune the scripts
      var scripts = svg.querySelectorAll('script');
      var scriptsToEval = [];
      var script, scriptType;

      for (var k = 0, scriptsLen = scripts.length; k < scriptsLen; k++) {
        scriptType = scripts[k].getAttribute('type');

        // Only process javascript types.
        // SVG defaults to 'application/ecmascript' for unset types
        if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {

          // innerText for IE, textContent for other browsers
          script = scripts[k].innerText || scripts[k].textContent;

          // Stash
          scriptsToEval.push(script);

          // Tidy up and remove the script element since we don't need it anymore
          svg.removeChild(scripts[k]);
        }
      }

      // Run/Eval the scripts if needed
      if (scriptsToEval.length > 0 && (evalScripts === 'always' || (evalScripts === 'once' && !ranScripts[imgUrl]))) {
        for (var l = 0, scriptsToEvalLen = scriptsToEval.length; l < scriptsToEvalLen; l++) {

          // :NOTE: Yup, this is a form of eval, but it is being used to eval code
          // the caller has explictely asked to be loaded, and the code is in a caller
          // defined SVG file... not raw user input.
          //
          // Also, the code is evaluated in a closure and not in the global scope.
          // If you need to put something in global scope, use 'window'
          new Function(scriptsToEval[l])(window); // jshint ignore:line
        }

        // Remember we already ran scripts for this svg
        ranScripts[imgUrl] = true;
      }

      // Replace the image with the svg
      el.parentNode.replaceChild(svg, el);

      // Increment the injected count
      injectCount++;

      callback(svg);
    });
  };

  /**
   * Array.forEach() polyfill for <= IE8
   * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
   */
  if (!Array.prototype.forEach) {
    Array.prototype.forEach = function (fn, scope) {
      if (this === void 0 || this === null || typeof fn !== 'function') {
        throw new TypeError();
      }

      /* jshint bitwise: false */
      var i, len = this.length >>> 0;
      /* jshint bitwise: true */

      for (i = 0; i < len; ++i) {
        if (i in this) {
          fn.call(scope, this[i], i, this);
        }
      }
    };
  }

  /**
   * SVGInjector
   *
   * Replace the given elements with their full inline SVG DOM elements.
   *
   * :NOTE: We are using get/setAttribute with SVG because the SVG DOM spec differs from HTML DOM and
   * can return other unexpected object types when trying to directly access svg properties.
   * ex: "className" returns a SVGAnimatedString with the class value found in the "baseVal" property,
   * instead of simple string like with HTML Elements.
   *
   * @param {mixes} Array of or single DOM element
   * @param {object} options
   * @param {function} callback
   * @return {object} Instance of SVGInjector
   */
  var SVGInjector = function (elements, options, done) {

    // Options & defaults
    options = options || {};

    // Should we run the scripts blocks found in the SVG
    // 'always' - Run them every time
    // 'once' - Only run scripts once for each SVG
    // [false|'never'] - Ignore scripts
    var evalScripts = options.evalScripts || 'always';

    // Location of fallback pngs, if desired
    var pngFallback = options.pngFallback || false;

    // Callback to run during each SVG injection, returning the SVG injected
    var eachCallback = options.each;

    // Do the injection...
    if (isDefined(elements.length)) {
      var elementsLoaded = 0;
      Array.prototype.forEach.call(elements, function (element) {
        injectElement(element, evalScripts, pngFallback, function (svg) {
          if (isFunction(eachCallback)) eachCallback(svg);
          if (done && elements.length === ++elementsLoaded) done(elementsLoaded);
        });
      });
    }
    else {
      if (elements) {
        injectElement(elements, evalScripts, pngFallback, function (svg) {
          if (isFunction(eachCallback)) eachCallback(svg);
          if (done) done(1);
        });
      }
      else {
        if (done) done(0);
      }
    }
  };

  /* global module, exports: true, define */
  // Node.js or CommonJS
  if (typeof module === 'object' && typeof module.exports === 'object') {
    module.exports = exports = SVGInjector;
  }
  // AMD support
  else if (isFunction(define) && define.amd) {
    define(function () {
      return SVGInjector;
    });
  }
  // Otherwise, attach to window as global
  else if (typeof window === 'object') {
    window.SVGInjector = SVGInjector;
  }
  /* global -module, -exports, -define */

}(window, document));
<|endoftext|>


<commit_before>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Promise from 'bluebird';

/**
 * An IndexedDB store backend where the actual backend sits in a web
 * worker.
 *
 * Construct a new Indexed Database store backend. This requires a call to
 * connect() before this store can be used.
 * @constructor
 * @param {string} workerScript URL to the worker script
 * @param {string=} dbName Optional database name. The same name must be used
 * to open the same database.
 * @param {Object} WorkerApi The web worker compatible interface object
 */
const RemoteIndexedDBStoreBackend = function RemoteIndexedDBStoreBackend(
    workerScript, dbName, WorkerApi,
) {
    this._workerScript = workerScript;
    this._dbName = dbName;
    this._workerApi = WorkerApi;
    this._worker = null;
    this._nextSeq = 0;
    // The currently in-flight requests to the actual backend
    this._inFlight = {
        // seq: promise,
    };
    this._startPromise = null;
};

RemoteIndexedDBStoreBackend.prototype = {
    /**
     * Attempt to connect to the database. This can fail if the user does not
     * grant permission.
     * @return {Promise} Resolves if successfully connected.
     */
    connect: function() {
        return this._ensureStarted().then(() => this._doCmd('connect'));
    },

    /**
     * Clear the entire database. This should be used when logging out of a client
     * to prevent mixing data between accounts.
     * @return {Promise} Resolved when the database is cleared.
     */
    clearDatabase: function() {
        return this._ensureStarted().then(() => this._doCmd('clearDatabase'));
    },

    /**
     * @return {Promise} Resolves with a sync response to restore the
     * client state to where it was at the last save, or null if there
     * is no saved sync data.
     */
    getSavedSync: function() {
        return this._doCmd('getSavedSync');
    },

    setSyncData: function(syncData) {
        return this._doCmd('setSyncData', [syncData]);
    },

    syncToDatabase: function(users) {
        return this._doCmd('syncToDatabase', [users]);
    },

    /**
     * Load all user presence events from the database. This is not cached.
     * @return {Promise<Object[]>} A list of presence events in their raw form.
     */
    getUserPresenceEvents: function() {
        return this._doCmd('getUserPresenceEvents');
    },

    _ensureStarted: function() {
        if (this._startPromise === null) {
            this._worker = new this._workerApi(this._workerScript);
            this._worker.onmessage = this._onWorkerMessage.bind(this);

            // tell the worker the db name.
            this._startPromise = this._doCmd('_setupWorker', [this._dbName]).then(() => {
                console.log("IndexedDB worker is ready");
            });
        }
        return this._startPromise;
    },

    _doCmd: function(cmd, args) {
        // wrap in a q so if the postMessage throws,
        // the promise automatically gets rejected
        return Promise.resolve().then(() => {
            const seq = this._nextSeq++;
            const def = Promise.defer();

            this._inFlight[seq] = def;

            this._worker.postMessage({
                command: cmd,
                seq: seq,
                args: args,
            });

            return def.promise;
        });
    },

    _onWorkerMessage: function(ev) {
        const msg = ev.data;

        if (msg.command == 'cmd_success' || msg.command == 'cmd_fail') {
            if (msg.seq === undefined) {
                console.error("Got reply from worker with no seq");
                return;
            }

            const def = this._inFlight[msg.seq];
            if (def === undefined) {
                console.error("Got reply for unknown seq " + msg.seq);
                return;
            }
            delete this._inFlight[msg.seq];

            if (msg.command == 'cmd_success') {
                def.resolve(msg.result);
            } else {
                def.reject(msg.error);
            }
        } else {
            console.warn("Unrecognised message from worker: " + msg);
        }
    },
};

export default RemoteIndexedDBStoreBackend;
<commit_msg>Make local variable look less like a global<commit_after>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Promise from 'bluebird';

/**
 * An IndexedDB store backend where the actual backend sits in a web
 * worker.
 *
 * Construct a new Indexed Database store backend. This requires a call to
 * connect() before this store can be used.
 * @constructor
 * @param {string} workerScript URL to the worker script
 * @param {string=} dbName Optional database name. The same name must be used
 * to open the same database.
 * @param {Object} WorkerApi The web worker compatible interface object
 */
const RemoteIndexedDBStoreBackend = function RemoteIndexedDBStoreBackend(
    workerScript, dbName, workerApi,
) {
    this._workerScript = workerScript;
    this._dbName = dbName;
    this._workerApi = workerApi;
    this._worker = null;
    this._nextSeq = 0;
    // The currently in-flight requests to the actual backend
    this._inFlight = {
        // seq: promise,
    };
    this._startPromise = null;
};

RemoteIndexedDBStoreBackend.prototype = {
    /**
     * Attempt to connect to the database. This can fail if the user does not
     * grant permission.
     * @return {Promise} Resolves if successfully connected.
     */
    connect: function() {
        return this._ensureStarted().then(() => this._doCmd('connect'));
    },

    /**
     * Clear the entire database. This should be used when logging out of a client
     * to prevent mixing data between accounts.
     * @return {Promise} Resolved when the database is cleared.
     */
    clearDatabase: function() {
        return this._ensureStarted().then(() => this._doCmd('clearDatabase'));
    },

    /**
     * @return {Promise} Resolves with a sync response to restore the
     * client state to where it was at the last save, or null if there
     * is no saved sync data.
     */
    getSavedSync: function() {
        return this._doCmd('getSavedSync');
    },

    setSyncData: function(syncData) {
        return this._doCmd('setSyncData', [syncData]);
    },

    syncToDatabase: function(users) {
        return this._doCmd('syncToDatabase', [users]);
    },

    /**
     * Load all user presence events from the database. This is not cached.
     * @return {Promise<Object[]>} A list of presence events in their raw form.
     */
    getUserPresenceEvents: function() {
        return this._doCmd('getUserPresenceEvents');
    },

    _ensureStarted: function() {
        if (this._startPromise === null) {
            this._worker = new this._workerApi(this._workerScript);
            this._worker.onmessage = this._onWorkerMessage.bind(this);

            // tell the worker the db name.
            this._startPromise = this._doCmd('_setupWorker', [this._dbName]).then(() => {
                console.log("IndexedDB worker is ready");
            });
        }
        return this._startPromise;
    },

    _doCmd: function(cmd, args) {
        // wrap in a q so if the postMessage throws,
        // the promise automatically gets rejected
        return Promise.resolve().then(() => {
            const seq = this._nextSeq++;
            const def = Promise.defer();

            this._inFlight[seq] = def;

            this._worker.postMessage({
                command: cmd,
                seq: seq,
                args: args,
            });

            return def.promise;
        });
    },

    _onWorkerMessage: function(ev) {
        const msg = ev.data;

        if (msg.command == 'cmd_success' || msg.command == 'cmd_fail') {
            if (msg.seq === undefined) {
                console.error("Got reply from worker with no seq");
                return;
            }

            const def = this._inFlight[msg.seq];
            if (def === undefined) {
                console.error("Got reply for unknown seq " + msg.seq);
                return;
            }
            delete this._inFlight[msg.seq];

            if (msg.command == 'cmd_success') {
                def.resolve(msg.result);
            } else {
                def.reject(msg.error);
            }
        } else {
            console.warn("Unrecognised message from worker: " + msg);
        }
    },
};

export default RemoteIndexedDBStoreBackend;
<|endoftext|>


<commit_before><commit_msg>Update paths<commit_after><|endoftext|>


<commit_before>'use strict';
/**
 * @file Define initial handlers,
 *
 * Trade grant_tokens for access_tokens.
 *
 */
var restify = require('restify');
var async = require('async');
var rarity = require('rarity');

var TempToken = require('../../models/temp-token.js');
var util = require('../../util.js');
var redirectToReturnTo = util.redirectToReturnTo;

/**
 * This handler starts providing a new account onto AnyFetch.
 * We check the request is valid, create a new tempToken and call the handler for new account.
 * The tempToken is then saved.
 *
 * @param {Object} req Request object from the client
 * @param {Object} res Response we want to return
 * @param {Function} next Callback to call once res has been populated.
 */
module.exports.getGenerator = function getGenerator(redirectToService, config) {
  return function connectGet(req, res, next) {
    var returnTo = req.params.return_to || process.env.MANAGER_URL || "https://manager.anyfetch.com";

    if(!req.params.code) {
      return next(new restify.MissingParameterError("Missing code parameter."));
    }

    async.waterfall([
      function callRedirectToService(cb) {
        redirectToService(config.providerUrl + '/init/callback', cb);
      },
      function removeTempToken(redirectUrl, preData, cb) {
        if(!cb) {
          cb = preData;
          preData = null;
        }
        TempToken.remove({anyfetchCode: req.params.code}, rarity.carryAndSlice([redirectUrl, preData], 3, cb));
      },
      function saveTempToken(redirectUrl, preData, cb) {
        var tempToken = new TempToken({
          anyfetchCode: req.params.code,
          returnTo: returnTo,
          data: preData
        });

        tempToken.save(rarity.carryAndSlice([redirectUrl], 2, cb));
      },
      function redirectUser(redirectUrl, cb) {
        if(typeof redirectUrl !== "string") {
          return cb(new Error("Redirect url must be a string, sent:" + redirectUrl));
        }

        req.ANYFETCH_SESSION.code = req.params.code;
        res.send(302, null, {
          location: redirectUrl,
        });

        cb(null);
      }
    ], function(err) {
      if(err) {
        util.logError(err, req, {params: req.params, returnTo: returnTo});
        redirectToReturnTo(res, returnTo, {state: 'danger', message: err.toString()});
        return next();
      }

      next();
    });
  };
};
<commit_msg>Added some comments<commit_after>'use strict';
/**
 * @file Define initial handlers,
 *
 * Trade grant_tokens for access_tokens.
 *
 */
var restify = require('restify');
var async = require('async');
var rarity = require('rarity');

var TempToken = require('../../models/temp-token.js');
var util = require('../../util.js');
var redirectToReturnTo = util.redirectToReturnTo;

/**
 * This handler starts providing a new account onto AnyFetch.
 * We check the request is valid, create a new tempToken and call the handler for new account.
 * The tempToken is then saved.
 *
 * @param {Object} req Request object from the client
 * @param {Object} res Response we want to return
 * @param {Function} next Callback to call once res has been populated.
 */
module.exports.getGenerator = function getGenerator(redirectToService, config) {
  return function connectGet(req, res, next) {
    // Return_to parameter optionally indicates where we should re-send the user after the authentication
    // It is not the same thing as the callback URL, where the user is sent after giving the grant.
    var returnTo = req.params.return_to || process.env.MANAGER_URL || "https://manager.anyfetch.com";

    if(!req.params.code) {
      return next(new restify.MissingParameterError("Missing code parameter."));
    }

    async.waterfall([
      function callRedirectToService(cb) {
        redirectToService(config.providerUrl + '/init/callback', cb);
      },
      function removeTempToken(redirectUrl, preData, cb) {
        if(!cb) {
          cb = preData;
          preData = null;
        }

        // Remove previous token (may happen when trying to connect the same provider twice in a row)
        TempToken.remove({
          anyfetchCode: req.params.code
        }, rarity.carryAndSlice([redirectUrl, preData], 3, cb));
      },
      function saveTempToken(redirectUrl, preData, cb) {
        // Write the tempToken. We'll retrieve it later, in /init/callback.
        var tempToken = new TempToken({
          anyfetchCode: req.params.code,
          returnTo: returnTo,
          data: preData
        });

        tempToken.save(rarity.carryAndSlice([redirectUrl], 2, cb));
      },
      function redirectUser(redirectUrl, cb) {
        if(typeof redirectUrl !== "string") {
          return cb(new Error("Redirect url must be a string, sent:" + redirectUrl));
        }

        // Store current code in session, we'll use it later to retrieve our temp token.
        // This is not REST, but it makes our lives easier
        req.ANYFETCH_SESSION.code = req.params.code;
        res.send(302, null, {
          location: redirectUrl,
        });

        cb(null);
      }
    ], function(err) {
      if(err) {
        util.logError(err, req, {params: req.params, returnTo: returnTo});
        redirectToReturnTo(res, returnTo, {state: 'danger', message: err.toString()});
        return next();
      }

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