<commit_before>export { Same, Bool, Int };

/**
 * Provides methods for converting nothing (just return original value).
 */
class Same {

  /** @return {any} Return the input value directly. */
  adjust( value ) {
    return value;
  }

  /**
   * @return {function}
   *   Return a function object. When calling the returned function object with one value parameter, it will return
   * the adjusted value which is retricted by this object.
   */
  getAdjuster() {
    return this.adjust.bind( this );
  }

//!!! ...unfinished... (2021/05/26) Maybe need a parameter to restrict the maximum generated value count, or value upper bound.
// Otherwise, too large value may not feasible to be tested.

  /**
   * Return a generator which produces a sequence of two-value pair.
   *
   * For ValueRange.Same, there is no meaningful testable value pair could be generated. The reason is that any value is legal for it.
   *
   * @yield {object}
   *   Every time yield an array with two number properties: { valueInput, valueOutput }. The valueOutput is a value from valueRangeMin to
   * valueRangeMax. The valueInput is a value which could be adjusted to valueOutput by this ValueRange object.
   */
  * valueInputOutputGenerator() {
    yield { valueInput: 0, valueOutput: 0 };
  }

  /**
   * Return a random integer between min and max. (This function comes from MDN's Math.random().)
   *
   * @param {number} min The the minimum integer. (inclusive)
   * @param {number} max The the maximum integer. (inclusive)
   */
  static getRandomIntInclusive( min, max ) {
    min = Math.ceil( min );
    max = Math.floor( max );
    return Math.floor( Math.random() * ( max - min + 1 ) + min );
  }
}

/** The only one ValueRange.Same instance. */
Same.Singleton = new Same;

/**
 * Provides methods for converting weight (a number) to boolean.
 */
class Bool extends Same {

  /** @return {boolean} Convert number value into false or true. */
  adjust( value ) {
    // If value is not an integer, the remainder will always not zero. So convert it to integer first.
    //
    // According to negative or positive, the remainder could be one of [ -1, 0, +1 ].
    // So simply check it whether is 0 (instead of check both -1 and +1), could result in false or true.
    return ( ( Math.trunc( value ) % 2 ) != 0 );
  }

  /**
   * For ValueRange.Bool, two two-value pairs will be generated in sequence.
   *
   * @override
   */
  * valueInputOutputGenerator() {

    let randomBaseInt = Same.getRandomIntInclusive( -100, +100 ); // (-100 and +100 just chosen arbitrarily.)
    let randomBaseIntEven = randomBaseInt * 2; // Any integer multiplied by 2 will be an even number.

    // An even value with fractional part will become 0 by Bool.adjust().
    let valueInputZero = ( randomBaseIntEven + 0 ) + Math.random();
    yield { valueInput: valueInputZero, valueOutput: 0 };

    // A odd value with fractional part will become 1 by Bool.adjust().
    let valueInputOne  = ( randomBaseIntEven + 1 ) + Math.random();
    yield { valueInput: valueInputOne, valueOutput: 1 };
  }

}

/** The only one ValueRange.Bool instance. */
Bool.Singleton = new Bool;

/**
 * Provides methods for converting weight (a number) to integer between min and max (both are integers).
 */
class Int extends Same {

  /**
   * @param {number} min The minimum value (as integer).
   * @param {number} max The maximum value (as integer).
   */
  constructor( min, max ) {
    super();
    this.min = Math.trunc( Math.min( min, max ) ); // Confirm the minimum. Convert to an integer.
    this.max = Math.trunc( Math.max( min, max ) ); // Confirm the maximum. Convert to an integer.
    this.kinds = ( this.max - this.min ) + 1; // How many possible integer between them.
  }

  /**
   * @return {number} Return the trucated value (i.e. integer). The returned value is forcibly between min and max (as integer too).
   */
  adjust( value ) {
    let valueInt = Math.trunc( value ); // Convert to an integer.

    // Rearrange valueInt between min and max fairly (in probability).
    //
    // A1: Why not use remainder operator (%) directly?
    // Q1: Because remainder always has the same sign as dividend, this can not handle the situation which min and
    //     max have different sign.
    //
    // A2: Why not just restrict all value less than min to valueMin and value greater than max to max?
    // Q2: Although this could restrict value in range, it will skew the probability of every value in the range.
    //     Unfair probability could be harmful to evolution algorithm.
    //
    let quotient = ( valueInt - this.min ) / this.kinds;
    let quotientInt = Math.floor( quotient );  // So that negative value could be handled correctly.
    let result = valueInt - ( quotientInt * this.kinds );
    return result;
  }

  /**
   * For ValueRange.Int, this.kinds two-value pairs will be generated in sequence.
   *
   * @override
   */
  * valueInputOutputGenerator() {

    let randomBaseInt = Same.getRandomIntInclusive( -10, +10 ); // (-10 and +10 just chosen arbitrarily.)

    // An integer which has the same remainder as randomBaseInt when divided by this.kinds.
    let randomBaseIntCongruence = randomBaseInt * this.kinds;

    for ( let i = 0; i < this.kinds; ++i ) {
      let valueOutputInt = ( this.min + i );

      // An integer which could become valueOutputInt when adjusted by Int.adjust().
      let valueInputInt = randomBaseIntCongruence + valueOutputInt;

      // An floating-point number (the integer with fractional part) which could become valueOutputInt when adjusted by Int.adjust().
      let valueInputFloat = valueInputInt + Math.random();

      yield { valueInput: valueInputFloat, valueOutput: valueOutputInt };
    }
  }

}
<commit_msg>Update ValueRange.js<commit_after>export { Same, Bool, Int };

/**
 * Provides methods for converting nothing (just return original value).
 */
class Same {

  /** @return {any} Return the input value directly. */
  adjust( value ) {
    return value;
  }

  /**
   * @return {function}
   *   Return a function object. When calling the returned function object with one value parameter, it will return
   * the adjusted value which is retricted by this object.
   */
  getAdjuster() {
    return this.adjust.bind( this );
  }

//!!! ...unfinished... (2021/05/26) Maybe need a parameter to restrict the maximum generated value count, or value upper bound.
// Otherwise, too large value may not feasible to be tested.

  /**
   * Return a generator which produces a sequence of two-value pair.
   *
   * For ValueRange.Same, there is no meaningful testable value pair could be generated. The reason is that any value is legal for it.
   *
   * @yield {object}
   *   Every time yield an array with two number properties: { valueInput, valueOutput }. The valueOutput is a value from valueRangeMin to
   * valueRangeMax. The valueInput is a value which could be adjusted to valueOutput by this ValueRange object.
   */
  * valueInputOutputGenerator() {
    yield { valueInput: 0, valueOutput: 0 };
  }

  /**
   * Return a random integer between min and max. (This function comes from MDN's Math.random().)
   *
   * @param {number} min The the minimum integer. (inclusive)
   * @param {number} max The the maximum integer. (inclusive)
   */
  static getRandomIntInclusive( min, max ) {
    min = Math.ceil( min );
    max = Math.floor( max );
    return Math.floor( Math.random() * ( max - min + 1 ) + min );
  }
}

/** The only one ValueRange.Same instance. */
Same.Singleton = new Same;

/**
 * Provides methods for converting weight (a number) to boolean.
 */
class Bool extends Same {

  /** @return {boolean} Convert number value into false or true. */
  adjust( value ) {
    // If value is not an integer, the remainder will always not zero. So convert it to integer first.
    //
    // According to negative or positive, the remainder could be one of [ -1, 0, +1 ].
    // So simply check it whether is 0 (instead of check both -1 and +1), could result in false or true.
    return ( ( Math.trunc( value ) % 2 ) != 0 );
  }

  /**
   * For ValueRange.Bool, two two-value pairs will be generated in sequence.
   *
   * @override
   */
  * valueInputOutputGenerator() {

    let randomBaseInt = Same.getRandomIntInclusive( -100, +100 ); // (-100 and +100 just chosen arbitrarily.)
    let randomBaseIntEven = randomBaseInt * 2; // Any integer multiplied by 2 will be an even number.
    let randomBaseIntEvenSign = Math.sign( randomBaseIntEven );

    // An even value with fractional part will become 0 by Bool.adjust().
    let valueInputZero = ( randomBaseIntEven + 0 ) + ( randomBaseIntEvenSign * Math.random() );
    yield { valueInput: valueInputZero, valueOutput: 0 };

    // A odd value with fractional part will become 1 by Bool.adjust().
    let valueInputOne  = ( randomBaseIntEven + 1 ) + ( randomBaseIntEvenSign * Math.random() );
    yield { valueInput: valueInputOne, valueOutput: 1 };
  }

}

/** The only one ValueRange.Bool instance. */
Bool.Singleton = new Bool;

/**
 * Provides methods for converting weight (a number) to integer between min and max (both are integers).
 */
class Int extends Same {

  /**
   * @param {number} min The minimum value (as integer).
   * @param {number} max The maximum value (as integer).
   */
  constructor( min, max ) {
    super();
    this.min = Math.trunc( Math.min( min, max ) ); // Confirm the minimum. Convert to an integer.
    this.max = Math.trunc( Math.max( min, max ) ); // Confirm the maximum. Convert to an integer.
    this.kinds = ( this.max - this.min ) + 1; // How many possible integer between them.
  }

  /**
   * @return {number} Return the trucated value (i.e. integer). The returned value is forcibly between min and max (as integer too).
   */
  adjust( value ) {
    let valueInt = Math.trunc( value ); // Convert to an integer.

    // Rearrange valueInt between min and max fairly (in probability).
    //
    // A1: Why not use remainder operator (%) directly?
    // Q1: Because remainder always has the same sign as dividend, this can not handle the situation which min and
    //     max have different sign.
    //
    // A2: Why not just restrict all value less than min to valueMin and value greater than max to max?
    // Q2: Although this could restrict value in range, it will skew the probability of every value in the range.
    //     Unfair probability could be harmful to evolution algorithm.
    //
    let quotient = ( valueInt - this.min ) / this.kinds;
    let quotientInt = Math.floor( quotient );  // So that negative value could be handled correctly.
    let result = valueInt - ( quotientInt * this.kinds );
    return result;
  }

  /**
   * For ValueRange.Int, this.kinds two-value pairs will be generated in sequence.
   *
   * @override
   */
  * valueInputOutputGenerator() {

    let randomBaseInt = Same.getRandomIntInclusive( -10, +10 ); // (-10 and +10 just chosen arbitrarily.)

    // An integer which has the same remainder as randomBaseInt when divided by this.kinds.
    let randomBaseIntCongruence = randomBaseInt * this.kinds;

    for ( let i = 0; i < this.kinds; ++i ) {
      let valueOutputInt = ( this.min + i );

      // An integer which could become valueOutputInt when adjusted by Int.adjust().
      let valueInputInt = randomBaseIntCongruence + valueOutputInt;
      let valueInputIntSign = Math.sign( valueInputInt );

      // An floating-point number (the integer with fractional part) which could become valueOutputInt when adjusted by Int.adjust().
      let valueInputFloat = valueInputInt + ( valueInputIntSign * Math.random() );

      yield { valueInput: valueInputFloat, valueOutput: valueOutputInt };
    }
  }

}
<|endoftext|>


<commit_before>"use strict";

/** Import an orthogonal tilemap from Tiled: Map Editor and draw on the screen
 * @constructor
 * @alias Splat.Tilemap
 * @param {Object} file JSON file exported from Tiled. This should be required in a scene enter
 * script and passed to the function.
 * @param {EntityPool} entities EntityPool from game.entities
 */
function ImportTilemap(file, entities) { // eslint-disable-line no-unused-vars

	var tile, image, image_index, tile_pos, cols, tileset, tileset_index = 0;
	var collider, layer, object;

	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];

		// Render Tile Layers
		if (layer.type == "tilelayer") {
			for (j = 0; j < layer.data.length; j++) {

				// Select tileset index based on firstgid and image index
				// Set image index minus firstgid for positioning math
				for (var k = 0; k < file.tilesets.length; k++) {
					if (layer.data[j] > file.tilesets[k].firstgid) {
						tileset_index = k;
					}
				}
				cols = file.tilesets[tileset_index].imagewidth / file.tilesets[tileset_index].tilewidth;
				image_index = layer.data[j] - file.tilesets[tileset_index].firstgid;
				tileset = file.tilesets[tileset_index];

				if (image_index >= 0) {

					// Create tile and get properties
					tile = entities.create();
					entities.set(tile, "name", "tile");
					entities.set(tile, "tile", true);
					entities.set(tile, "image", {"name": ""});
					entities.set(tile, "position", {"x": 0, "y": 0});
					image = entities.get(tile, "image");
					tile_pos = entities.get(tile, "position");

					// Position based on index
					tile_pos.x = (j % file.width) * file.tilewidth;
					tile_pos.y = Math.floor(j / file.width) * file.tileheight;

					// Character position z: 1 so anything without background true will layer over player
					tile_pos.z = (layer.properties.Background == "True") ? -1 : 2;

					// Select which "tile" of the tileset image to render
					image.name = tileset.image;
					image.sourceWidth = tileset.tilewidth;
					image.sourceHeight = tileset.tileheight;
					image.destinationWidth = tileset.tilewidth;
					image.destinationHeight = tileset.tileheight;
					image.sourceX = (image_index % cols) * tileset.tilewidth + ((image_index % cols) * tileset.spacing) + tileset.margin;
					image.sourceY = Math.floor(image_index / cols) * tileset.tileheight + (Math.floor(image_index / cols) * tileset.spacing) + tileset.margin;

				}
			}
		}

		// Loop object layer for collisions and spawn point
		// TODO Bug spawn chance triggers, doors, switches (buttons), warp zones, NPC Spawn points
		if (layer.type == "objectgroup") {
			for (var j = 0; j < layer.objects.length; j++) {
				object = layer.objects[j];

				// Collision box prefabs
				if (object.properties.Collidable == "True") {
					collider = entities.create();
					entities.set(collider, "name", "collider");
					entities.set(collider, "size", { "width": object.width, "height": object.height });
					entities.set(collider, "position", { "x": object.x, "y": object.y });
				}

				// Spawn points
				if (object.properties.Spawn == "True") {
					var spawn = entities.create();
					entities.set(spawn, "name", "spawn");
					entities.set(spawn, "spawn", true);
					entities.set(spawn, "size", { "width": object.width, "height": object.height });
					entities.set(spawn, "position", { "x": object.x, "y": object.y });
				}
			}
		}
	}

	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	var container = entities.create();
	entities.set(container, "name", "container");
	entities.set(container, "container", true);
	entities.set(container, "size", map_size);

}

module.exports = ImportTilemap;
<commit_msg>add some object property parsing to make truthy and falsy values booleans and numbers ints instead of strings<commit_after>"use strict";

/** Import an orthogonal tilemap from Tiled: Map Editor and draw on the screen
 * @constructor
 * @alias Splat.Tilemap
 * @param {Object} file JSON file exported from Tiled. This should be required in a scene enter
 * script and passed to the function.
 * @param {EntityPool} entities EntityPool from game.entities
 */
function ImportTilemap(file, entities) { // eslint-disable-line no-unused-vars

	var tile, image, image_index, tile_pos, cols, tileset, tileset_index = 0;
	var collider, layer, object, entity;

	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];

		// Render Tile Layers
		if (layer.type == "tilelayer") {
			for (j = 0; j < layer.data.length; j++) {

				// Select tileset index based on firstgid and image index
				// Set image index minus firstgid for positioning math
				for (var k = 0; k < file.tilesets.length; k++) {
					if (layer.data[j] > file.tilesets[k].firstgid) {
						tileset_index = k;
					}
				}
				cols = file.tilesets[tileset_index].imagewidth / file.tilesets[tileset_index].tilewidth;
				image_index = layer.data[j] - file.tilesets[tileset_index].firstgid;
				tileset = file.tilesets[tileset_index];

				if (image_index >= 0) {

					// Create tile and get properties
					tile = entities.create();
					entities.set(tile, "name", "tile");
					entities.set(tile, "tile", true);
					entities.set(tile, "image", {"name": ""});
					entities.set(tile, "position", {"x": 0, "y": 0});
					image = entities.get(tile, "image");
					tile_pos = entities.get(tile, "position");

					// Position based on index
					tile_pos.x = (j % file.width) * file.tilewidth;
					tile_pos.y = Math.floor(j / file.width) * file.tileheight;

					// Character position z: 1 so anything without background true will layer over player
					tile_pos.z = (layer.properties.Background == "True") ? -1 : 2;

					// Select which "tile" of the tileset image to render
					image.name = tileset.image;
					image.sourceWidth = tileset.tilewidth;
					image.sourceHeight = tileset.tileheight;
					image.destinationWidth = tileset.tilewidth;
					image.destinationHeight = tileset.tileheight;
					image.sourceX = (image_index % cols) * tileset.tilewidth + ((image_index % cols) * tileset.spacing) + tileset.margin;
					image.sourceY = Math.floor(image_index / cols) * tileset.tileheight + (Math.floor(image_index / cols) * tileset.spacing) + tileset.margin;

				}
			}
		}

		// Loop object layer for collisions and spawn point
		// TODO Bug spawn chance triggers, doors, switches (buttons), warp zones, NPC Spawn points
		if (layer.type == "objectgroup") {
			for (var j = 0; j < layer.objects.length; j++) {
				object = layer.objects[j];
				entity = entities.create();
				entities.set(entity, "size", { "width": object.width, "height": object.height });
				entities.set(entity, "position", { "x": object.x, "y": object.y });
				Object.keys(object.properties).forEach(function(key) {
					if(!isNaN(object.properties[key])) {
						object.properties[key] = parseInt(object.properties[key], 10);
					}
					if(new String(object.properties[key]).toLowerCase() == "true" || object.properties[key] == "1") {
						object.properties[key] = true;
					}
					if(new String(object.properties[key]).toLowerCase() == "false" || object.properties[key] == "0") {
						object.properties[key] = false;
					}
				});
				entities.set(entity, "tiled_properties", object.properties);

				// Collision box prefabs
				if (object.properties.Collidable) {
					collider = entities.create();
					entities.set(entity, "name", "collider");
					entities.set(entity, "collisions", []);
				}

				// Spawn points
				if (object.properties.Spawn) {
					var spawn = entities.create();
					entities.set(entity, "name", "spawn");
					entities.set(entity, "spawn", true);
				}
			}
		}
	}

	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	var container = entities.create();
	entities.set(container, "name", "container");
	entities.set(container, "container", true);
	entities.set(container, "position", {"x": 0, "y": 0});
	entities.set(container, "size", map_size);

}

module.exports = ImportTilemap;
<|endoftext|>


<commit_before>export {Base, Concrete, Aggregate};

/**
 * The base class for representing progress as number berween [0, 100] inclusive. Acceptable by Receiver.Base.
 *
 * The max() always returns 100. The value() returns number berween [0, 100] inclusive.
 */
class Base {
  /**
   * Dummy.
   * @return Always return 0. Sub-class should override this method.
   */
  get value() {
    return 0;
  }

  /** @return Always is 100. */
  get max() {
    return 100;
  }
}

/**
 * Aggregate all progress and represents them as percentag. Acceptable by Receiver.Base.
 *
 * The Concrete.max always returns 100. The Concrete.value returns number berween [0, 100] inclusive.
 */
class Concrete extends Base {
  constructor() {
    super();
    this.accumulation = 0;
    this.total = -1; // Negative indicates not initialized.
  }

  /**
   * @return
   *   The progress as number between [0, 100] inclusive.
   *   Always 0, if this.total is negative.
   *   Always 100, if this.total is zero.
   *   Otherwise, return the ratio of ( this.accumulation / this.total ).
   */
  get value() {
    if (this.total < 0)
      return 0;   // Return 0 if total is not initialized. Otherwise, the Aggregate.value will immediately 100.
    if (this.total == 0)
      return 100; // Return 100 if total is indeed zero. Otherwise, the Aggregate.value will never 100.

    let accumulation = Math.max(0, Math.min(this.accumulation, this.total)); // Restrict between [0, total].
    let percentage = ( accumulation / this.total ) * 100;
    return percentage;
  }
}

/**
 * Aggregate all children progress and represents them as percentage.
 */
class Aggregate extends Base {
  /**
   * @param {Percentage.Base[]} children An array of Percentage which will be aggregate.
   */
  constructor(children = []) {
    super();
    this.childProgressParts = children;
  }

  /**
   * @param {Percentage.Base} progressPart Another Progress.Percentage object.
   */
  addChild(progressPart) {
    this.childProgressParts.push(progressPart);
  }

  /**
   * @return The average of all children progress as number between [0, 100] inclusive.
   */
  get value() {
    let valueSum = 0, maxSum = 0;

    for (let progressPart of this.childProgressParts) {
      if (!progressPart)
        continue;

      let partMax = progressPart.max;
      if (partMax <= 0)
        continue; // Skip illegal progress.

      let partValue = progressPart.value;
      partValue = Math.max(0, Math.min(partValue, partMax)); // Restrict between [0, partMax].

      valueSum += partValue;
      maxSum += partMax;
    }

    if (maxSum <= 0)
      return 0; // Return zero if the total is illegal.

    let percentage = ( valueSum / maxSum ) * 100;
    return percentage;
  }

}
<commit_msg>Update Percentage.js<commit_after>export {Base, Concrete, Aggregate};

/**
 * The base class for representing progress as number berween [0, 100] inclusive. Acceptable by Receiver.Base.
 *
 * The max() always returns 100. The value() returns number berween [0, 100] inclusive.
 */
class Base {
  /**
   * Dummy.
   * @return Always return 0. Sub-class should override this method.
   */
  get value() {
    return 0;
  }

  /** @return Always is 100. */
  get max() {
    return 100;
  }
}

/**
 * Aggregate all progress and represents them as percentag. Acceptable by Receiver.Base.
 *
 * The Concrete.max always returns 100. The Concrete.value returns number berween [0, 100] inclusive.
 */
class Concrete extends Base {
  constructor() {
    super();
    this.accumulation = 0;
    this.total = -1; // Negative indicates not initialized.
  }

  /** Reset this.accumulation to 0. */
  resetAccumulation() {
    this.accumulation = 0;
  }

  /**
   * @return
   *   The progress as number between [0, 100] inclusive.
   *   Always 0, if this.total is negative.
   *   Always 100, if this.total is zero.
   *   Otherwise, return the ratio of ( this.accumulation / this.total ).
   */
  get value() {
    if (this.total < 0)
      return 0;   // Return 0 if total is not initialized. Otherwise, the Aggregate.value will immediately 100.
    if (this.total == 0)
      return 100; // Return 100 if total is indeed zero. Otherwise, the Aggregate.value will never 100.

    let accumulation = Math.max(0, Math.min(this.accumulation, this.total)); // Restrict between [0, total].
    let percentage = ( accumulation / this.total ) * 100;
    return percentage;
  }
}

/**
 * Aggregate all children progress and represents them as percentage.
 */
class Aggregate extends Base {
  /**
   * @param {Percentage.Base[]} children An array of Percentage which will be aggregate.
   */
  constructor(children = []) {
    super();
    this.childProgressParts = children;
  }

  /**
   * @param {Percentage.Base} progressPart Another Progress.Percentage object.
   */
  addChild(progressPart) {
    this.childProgressParts.push(progressPart);
  }

  /** Reset all children's this.accumulation to 0. */
  resetAccumulation() {
    for ( let i = 0; i < this.childProgressParts.length; ++i ) {
      let progressPart = this.childProgressParts[ i ];
      if ( progressPart ) {
        progressPart.resetAccumulation();
      }
    }
  }

  /**
   * @return The average of all children progress as number between [0, 100] inclusive.
   */
  get value() {
    let valueSum = 0, maxSum = 0;

    // Use integer array index is faster than iterator.
    //for (let progressPart of this.childProgressParts) {
    for ( let i = 0; i < this.childProgressParts.length; ++i ) {
      let progressPart = this.childProgressParts[ i ];
      if ( !progressPart )
        continue;

      let partMax = progressPart.max;
      if ( partMax <= 0 )
        continue; // Skip illegal progress.

      let partValue = progressPart.value;
      partValue = Math.max( 0, Math.min( partValue, partMax ) ); // Restrict between [0, partMax].

      valueSum += partValue;
      maxSum += partMax;
    }

    if ( maxSum <= 0 )
      return 0; // Return zero if the total is illegal.

    let percentage = ( valueSum / maxSum ) * 100;
    return percentage;
  }

}
<|endoftext|>


<commit_before>var parser = require('swagger-parser'),
    Endpoint = require('../entities/endpoint'),
    Schema = require('../entities/schema'),
    Importer = require('./importer'),
    Project = require('../entities/project'),
    jsonHelper = require('../utils/json');

function Swagger() {
  this.metadata = null;
  this.$refs = null;
  this.filePath = null;
}

Swagger.prototype = new Importer();

Swagger.prototype._mapSecurityDefinitions = function(securityDefinitions) {
  var result = {};
  for(var name in securityDefinitions) {
    var type = securityDefinitions[name].type;
    result[type] = {};
    switch(type) {
      case 'apiKey':
        if (securityDefinitions[name].in !== undefined && securityDefinitions[name].in != '') {
          result[type][securityDefinitions[name].in] = {
            name: securityDefinitions[name].name,
            value: ''
          };
        }
        break;
      case 'oauth2':
        result[type] = {
          name: name,
          authorizationUrl: securityDefinitions[name].authorizationUrl || '',
          scopes: slScopes,
          tokenUrl: securityDefinitions[name].tokenUrl || ''
        };

        var slScopes = [], swaggerScopes = securityDefinitions[name].scopes;

        if (swaggerScopes) {
          for(var key in swaggerScopes) {
            var scope = {};
            scope['name'] = key;
            scope['value'] = swaggerScopes[key];
            slScopes.push(scope);
          }
        }

        if (securityDefinitions[name].flow) {
          result[type]['flow'] = securityDefinitions[name].flow;
        }

        if (slScopes.length > 0) {
          result[type]['scopes'] = slScopes;
        }

        break;
      case 'basic':
        result[type]['header'] = {
          name: securityDefinitions[name].name,
          value: '',
          description: securityDefinitions[name].description || ''
        };
        break;
    }
  }
  return result;
};

Swagger.prototype._mapSchema = function(schemaDefinitions) {
  var result = [];
  for (var schemaName in schemaDefinitions) {
    var sd = new Schema(schemaName);
    sd.Name = schemaName;
    sd.Definition = jsonHelper.stringify(schemaDefinitions[schemaName], 4);
    result.push(sd);
  }
  return result;
};

Swagger.prototype._mapQueryString = function(params) {
  var queryString = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (param.in !== 'query') {
      //skip other type of params
      continue;
    }
    queryString.properties[param.name] = {
      type: param.type,
      description: param.description
    };
    if (param.required) {
      queryString.required.push(param.name);
    }
    if (param.type === 'array') {
      queryString.properties[param.name].items = param.items;
    }
  }
  return queryString;
};

Swagger.prototype._mapURIParams = function(params) {
  var pathParams = {};
  for (var i in params) {
    var param = params[i];
    if (param.hasOwnProperty('$ref')) {
      //any unresolved data?!?
      //console.log(i, param)
    }
    if (param.in !== 'path') {
      //skip other type of params
      continue;
    }
    pathParams[param.name] = {
      type: param.type,
      description: param.description
    };

    if (param.type === 'array') {
      pathParams[param.name].items = param.items;
    }
  }

  return pathParams;
};

Swagger.prototype._mapRequestBody = function(params, reqType) {
  var data = {mimeType: reqType || null, body: {properties: {}, required: []}, example: ''};

  for (var i in params) {
    var param = params[i];
    if (param.in !== 'body' && param.in !== 'formData') {
      //skip other type of params
      if (param.hasOwnProperty('$ref')) {
        //TODO if $ref param
      }
      continue;
    }
    data.body.properties[param.name] = {};

    switch(param.in) {
      case 'body':
        data.body.properties[param.name] = param.schema;
        break;
      default:
        data.body.properties[param.name]['type'] = param.type;
    }

    if (param.description) {
      data.body.properties[param.name].description = param.description;
    }

    if (param.required) {
      data.body.required.push(param.name);
    }
  }
  //remove required field if doesn't have anything inside it
  if (data.body.required.length == 0) {
    delete data.body.required;
  }
  return data;
};

Swagger.prototype._mapResponseBody = function(responseBody, resType) {
  var data = [], defaultCodeTaken = false;
  for (var code in responseBody) {
    var res = {mimeType: resType, body: {}, example: '', codes: []};
    if (responseBody[code].schema) {
      res.body = responseBody[code].schema;
    }
    if (responseBody[code].hasOwnProperty('examples')) {
      for(var t in responseBody[code].examples) {
        if (t === resType) {
          res.example = jsonHelper.stringify(responseBody[code].examples[t], 4);
        }
      }
    }

    res.description = responseBody[code].description || '';
    res.body = jsonHelper.stringify(res.body, 4);

    if (code === 'default') {
      //swagger default usually meant for error responses:
      //https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#responses-object
      code = 400;
    }
    if (code === 400 || code === '400') {
      if (defaultCodeTaken) continue;
      defaultCodeTaken = true;
    }

    res.codes.push(code);
    data.push(res);
  }

  return data;
};

Swagger.prototype._mapRequestHeaders = function(params) {
  var data = {type: 'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (param.in !== 'header') {
      //skip other type of params
      continue;
    }
    data.properties[param.name] = {
      type: param.type,
      description: param.description || ''
    };
    if (param.required) {
      data.required.push(param.name);
    }
  }
  return data;
};

Swagger.prototype.loadFile = function (path, cb) {
  var me = this;
  this.filePath = path;

  parser.parse(path)
  .then(function(api, metadata) {
    me.data = api;
    me.metadata = metadata;
    parser.resolve(path)
      .then(function($refs) {
        try {
          me.$refs = $refs.values()[me.filePath];
        } catch(err) {
          //ignore reference error
        }
        cb();
      })
      .catch(cb);
  })
  .catch(cb);
};

/*Swagger.prototype.loadData = function(data, cb) {
  parser.validate(myAPI)
  .then(function(api) {
    cb();
  })
  .catch(function(err) {
    ccb(err);
  });
};*/

//for now, if 'application/json' exist in supported type, use that
Swagger.prototype.findDefaultMimeType = function(mimeTypes) {
  if (!mimeTypes || mimeTypes.length <= 0) {
    return 'application/json';
  }
  for(var i in mimeTypes) {
    if (mimeTypes[i] === 'application/json') {
      return mimeTypes[i];
    }
  }
  return mimeTypes[0];
};

Swagger.prototype._import = function() {

  var defaultReqContentType = this.findDefaultMimeType(this.data.consumes),
      defaultResContentType = this.findDefaultMimeType(this.data.produces);

  this.project = new Project(this.data.info.title);
  this.project.Description = this.data.info.description || '';

  this.project.Environment.BasePath = this.data.basePath || '';
  this.project.Environment.Host = this.data.host || 'http://localhost:3000';
  this.project.Environment.Version = this.data.info.version;

  if (this.data.schemes && this.data.schemes.length > 0) {
    this.project.Environment.Protocols = this.data.schemes;
  }

  if (this.data.produces) {
    //taking the first as default one
    this.project.Environment.DefaultResponseType = defaultResContentType;
  }

  if (this.data.consumes) {
    //taking the first as default one
    this.project.Environment.DefaultRequestType = defaultReqContentType;
  }
  if (this.data.securityDefinitions) {
    this.project.SecuritySchemes = this._mapSecurityDefinitions(this.data.securityDefinitions);
  }

  for (var path in this.data.paths) {
    var methods = this.data.paths[path];
    var pathParams = {};
    if (methods.parameters) {
      pathParams = this._mapURIParams(methods.parameters);
    }

    for (var method in methods) {
      if (method === 'parameters') {
        continue;
      }
      var endpoint = new Endpoint(methods[method].operationId || ''),
        reqType = defaultReqContentType,
        resType = defaultResContentType;

      endpoint.Path = path;
      endpoint.Method = method;

      endpoint.Description = methods[method].description || methods[method].summary;
      endpoint.Summary = methods[method].summary || '';

      //map request body
      if (methods[method].consumes) {
        //taking only one
        reqType = this.findDefaultMimeType(methods[method].consumes);
      }
      if (endpoint.Method.toLowerCase() !== 'get' &&
          endpoint.Method.toLowerCase() !== 'head') {
        endpoint.Body = this._mapRequestBody(methods[method].parameters, reqType);
      }

      //map response body
      if (methods[method].produces) {
        //taking only one
        resType = this.findDefaultMimeType(methods[method].produces);
      }
      endpoint.Responses = this._mapResponseBody(methods[method].responses, resType);

      //map query string
      endpoint.QueryString = this._mapQueryString(methods[method].parameters);

      //map path params
      endpoint.PathParams = pathParams;

      //map headers
      endpoint.Headers = this._mapRequestHeaders(methods[method].parameters);

      //map security
      if (methods[method].security) {
        var securities = methods[method].security;
        for (var securityIndex in securities) {
          var keys = Object.keys(securities[securityIndex]);
          var securityName = keys[0];
          var scheme = this.data.securityDefinitions[securityName];
          if (!scheme) {
            //definition error
            continue;
          }
          switch(scheme.type) {
            case 'apiKey':
            case 'basic':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = true;
              break;
            case 'oauth2':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = securities[securityIndex][securityName];
              break;
          }
        }
      }

      this.project.addEndpoint(endpoint);
    }
  }

  var schemas = this._mapSchema(this.data.definitions);
  for(var i in schemas) {
    this.project.addSchema(schemas[i]);
  }
};

module.exports = Swagger;
<commit_msg>#5 - Support for 'default' code itself.<commit_after>var parser = require('swagger-parser'),
    Endpoint = require('../entities/endpoint'),
    Schema = require('../entities/schema'),
    Importer = require('./importer'),
    Project = require('../entities/project'),
    jsonHelper = require('../utils/json');

function Swagger() {
  this.metadata = null;
  this.$refs = null;
  this.filePath = null;
}

Swagger.prototype = new Importer();

Swagger.prototype._mapSecurityDefinitions = function(securityDefinitions) {
  var result = {};
  for(var name in securityDefinitions) {
    var type = securityDefinitions[name].type;
    result[type] = {};
    switch(type) {
      case 'apiKey':
        if (securityDefinitions[name].in !== undefined && securityDefinitions[name].in != '') {
          result[type][securityDefinitions[name].in] = {
            name: securityDefinitions[name].name,
            value: ''
          };
        }
        break;
      case 'oauth2':
        result[type] = {
          name: name,
          authorizationUrl: securityDefinitions[name].authorizationUrl || '',
          scopes: slScopes,
          tokenUrl: securityDefinitions[name].tokenUrl || ''
        };

        var slScopes = [], swaggerScopes = securityDefinitions[name].scopes;

        if (swaggerScopes) {
          for(var key in swaggerScopes) {
            var scope = {};
            scope['name'] = key;
            scope['value'] = swaggerScopes[key];
            slScopes.push(scope);
          }
        }

        if (securityDefinitions[name].flow) {
          result[type]['flow'] = securityDefinitions[name].flow;
        }

        if (slScopes.length > 0) {
          result[type]['scopes'] = slScopes;
        }

        break;
      case 'basic':
        result[type]['header'] = {
          name: securityDefinitions[name].name,
          value: '',
          description: securityDefinitions[name].description || ''
        };
        break;
    }
  }
  return result;
};

Swagger.prototype._mapSchema = function(schemaDefinitions) {
  var result = [];
  for (var schemaName in schemaDefinitions) {
    var sd = new Schema(schemaName);
    sd.Name = schemaName;
    sd.Definition = jsonHelper.stringify(schemaDefinitions[schemaName], 4);
    result.push(sd);
  }
  return result;
};

Swagger.prototype._mapQueryString = function(params) {
  var queryString = {type:'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (param.in !== 'query') {
      //skip other type of params
      continue;
    }
    queryString.properties[param.name] = {
      type: param.type,
      description: param.description
    };
    if (param.required) {
      queryString.required.push(param.name);
    }
    if (param.type === 'array') {
      queryString.properties[param.name].items = param.items;
    }
  }
  return queryString;
};

Swagger.prototype._mapURIParams = function(params) {
  var pathParams = {};
  for (var i in params) {
    var param = params[i];
    if (param.hasOwnProperty('$ref')) {
      //any unresolved data?!?
      //console.log(i, param)
    }
    if (param.in !== 'path') {
      //skip other type of params
      continue;
    }
    pathParams[param.name] = {
      type: param.type,
      description: param.description
    };

    if (param.type === 'array') {
      pathParams[param.name].items = param.items;
    }
  }

  return pathParams;
};

Swagger.prototype._mapRequestBody = function(params, reqType) {
  var data = {mimeType: reqType || null, body: {properties: {}, required: []}, example: ''};

  for (var i in params) {
    var param = params[i];
    if (param.in !== 'body' && param.in !== 'formData') {
      //skip other type of params
      if (param.hasOwnProperty('$ref')) {
        //TODO if $ref param
      }
      continue;
    }
    data.body.properties[param.name] = {};

    switch(param.in) {
      case 'body':
        data.body.properties[param.name] = param.schema;
        break;
      default:
        data.body.properties[param.name]['type'] = param.type;
    }

    if (param.description) {
      data.body.properties[param.name].description = param.description;
    }

    if (param.required) {
      data.body.required.push(param.name);
    }
  }
  //remove required field if doesn't have anything inside it
  if (data.body.required.length == 0) {
    delete data.body.required;
  }
  return data;
};

Swagger.prototype._mapResponseBody = function(responseBody, resType) {
  var data = [];
  for (var code in responseBody) {
    var res = {mimeType: resType, body: {}, example: '', codes: []};
    if (responseBody[code].schema) {
      res.body = responseBody[code].schema;
    }
    if (responseBody[code].hasOwnProperty('examples')) {
      for(var t in responseBody[code].examples) {
        if (t === resType) {
          res.example = jsonHelper.stringify(responseBody[code].examples[t], 4);
        }
      }
    }

    res.description = responseBody[code].description || '';
    res.body = jsonHelper.stringify(res.body, 4);

    res.codes.push(code);
    data.push(res);
  }

  return data;
};

Swagger.prototype._mapRequestHeaders = function(params) {
  var data = {type: 'object', properties: {}, required: []};
  for (var i in params) {
    var param = params[i];
    if (param.in !== 'header') {
      //skip other type of params
      continue;
    }
    data.properties[param.name] = {
      type: param.type,
      description: param.description || ''
    };
    if (param.required) {
      data.required.push(param.name);
    }
  }
  return data;
};

Swagger.prototype.loadFile = function (path, cb) {
  var me = this;
  this.filePath = path;

  parser.parse(path)
  .then(function(api, metadata) {
    me.data = api;
    me.metadata = metadata;
    parser.resolve(path)
      .then(function($refs) {
        try {
          me.$refs = $refs.values()[me.filePath];
        } catch(err) {
          //ignore reference error
        }
        cb();
      })
      .catch(cb);
  })
  .catch(cb);
};

/*Swagger.prototype.loadData = function(data, cb) {
  parser.validate(myAPI)
  .then(function(api) {
    cb();
  })
  .catch(function(err) {
    ccb(err);
  });
};*/

//for now, if 'application/json' exist in supported type, use that
Swagger.prototype.findDefaultMimeType = function(mimeTypes) {
  if (!mimeTypes || mimeTypes.length <= 0) {
    return 'application/json';
  }
  for(var i in mimeTypes) {
    if (mimeTypes[i] === 'application/json') {
      return mimeTypes[i];
    }
  }
  return mimeTypes[0];
};

Swagger.prototype._import = function() {

  var defaultReqContentType = this.findDefaultMimeType(this.data.consumes),
      defaultResContentType = this.findDefaultMimeType(this.data.produces);

  this.project = new Project(this.data.info.title);
  this.project.Description = this.data.info.description || '';

  this.project.Environment.BasePath = this.data.basePath || '';
  this.project.Environment.Host = this.data.host || 'http://localhost:3000';
  this.project.Environment.Version = this.data.info.version;

  if (this.data.schemes && this.data.schemes.length > 0) {
    this.project.Environment.Protocols = this.data.schemes;
  }

  if (this.data.produces) {
    //taking the first as default one
    this.project.Environment.DefaultResponseType = defaultResContentType;
  }

  if (this.data.consumes) {
    //taking the first as default one
    this.project.Environment.DefaultRequestType = defaultReqContentType;
  }
  if (this.data.securityDefinitions) {
    this.project.SecuritySchemes = this._mapSecurityDefinitions(this.data.securityDefinitions);
  }

  for (var path in this.data.paths) {
    var methods = this.data.paths[path];
    var pathParams = {};
    if (methods.parameters) {
      pathParams = this._mapURIParams(methods.parameters);
    }

    for (var method in methods) {
      if (method === 'parameters') {
        continue;
      }
      var endpoint = new Endpoint(methods[method].operationId || ''),
        reqType = defaultReqContentType,
        resType = defaultResContentType;

      endpoint.Path = path;
      endpoint.Method = method;

      endpoint.Description = methods[method].description || methods[method].summary;
      endpoint.Summary = methods[method].summary || '';

      //map request body
      if (methods[method].consumes) {
        //taking only one
        reqType = this.findDefaultMimeType(methods[method].consumes);
      }
      if (endpoint.Method.toLowerCase() !== 'get' &&
          endpoint.Method.toLowerCase() !== 'head') {
        endpoint.Body = this._mapRequestBody(methods[method].parameters, reqType);
      }

      //map response body
      if (methods[method].produces) {
        //taking only one
        resType = this.findDefaultMimeType(methods[method].produces);
      }
      endpoint.Responses = this._mapResponseBody(methods[method].responses, resType);

      //map query string
      endpoint.QueryString = this._mapQueryString(methods[method].parameters);

      //map path params
      endpoint.PathParams = pathParams;

      //map headers
      endpoint.Headers = this._mapRequestHeaders(methods[method].parameters);

      //map security
      if (methods[method].security) {
        var securities = methods[method].security;
        for (var securityIndex in securities) {
          var keys = Object.keys(securities[securityIndex]);
          var securityName = keys[0];
          var scheme = this.data.securityDefinitions[securityName];
          if (!scheme) {
            //definition error
            continue;
          }
          switch(scheme.type) {
            case 'apiKey':
            case 'basic':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = true;
              break;
            case 'oauth2':
              if (endpoint.SecuredBy.none) {
                endpoint.SecuredBy = {};
              }
              endpoint.SecuredBy[scheme.type] = securities[securityIndex][securityName];
              break;
          }
        }
      }

      this.project.addEndpoint(endpoint);
    }
  }

  var schemas = this._mapSchema(this.data.definitions);
  for(var i in schemas) {
    this.project.addSchema(schemas[i]);
  }
};

module.exports = Swagger;
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Simon Edwards <simon@simonzone.com>
 *
 * This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
 */
require('shelljs/global');
const path = require('path');
const fs = require('fs');
const packager = require('electron-packager');
const dependencyPruner = require('./dependency_pruner');
const log = console.log.bind(console);
const MODULE_VERSON = 69; // This version number also appears in thememanager.ts

const ignoreRegExp = [
  /^\/build_scripts\b/,
  /^\/extraterm-web-component-decorators\b/,
  /^\/extraterm-extension-api\b/,
  /^\/test\b/,
  /^\/build_tmp\b/,
  /^\/src\/typedocs\b/,
  /\.ts$/,
  /\.js\.map$/,
  /^\/\.git\//,
  /^\/docs\b/,
  /^\/resources\/extra_icons\b/,
  /^\/src\/test\b/,
  /^\/src\/testfiles\b/
];

const ignoreFunc = function ignoreFunc(filePath) {
  const result = ignoreRegExp.some( (exp) => exp.test(filePath));
  return result;
};

function appDir(platform) {
  return platform === "darwin" ? "Extraterm.app/Contents/Resources/app" : "resources/app";
}

function pruneNodeSass(versionedOutputDir, arch, platform) {
  const gutsDir = appDir(platform);
  const nodeSassVendorDir = path.join(versionedOutputDir, gutsDir, "node_modules/node-sass/vendor");

  rm('-rf', nodeSassVendorDir);

  const nodeSassBinaryDir = path.join(versionedOutputDir, gutsDir, "src/node-sass-binary");
  ["darwin-x64", "linux-ia32", "linux-x64", "win32-x64"].forEach( (name) => {
    if (name !== platform + "-" + arch) {
      rm('-rf', path.join(nodeSassBinaryDir, name + "-" + MODULE_VERSON));
    }
  });
}

function pruneTwemoji(versionedOutputDir, platform) {
  if (platform !== "linux") {
    const twemojiPath = path.join(versionedOutputDir, appDir(platform), "extraterm/resources/themes/default/fonts/Twemoji.ttf");
    rm(twemojiPath);
  }
}

function hoistSubprojectsModules(versionedOutputDir, platform) {
  const modulesDir = path.join(versionedOutputDir, appDir(platform), "node_modules");

  // Delete the symlinks.
  for (const item of ls(modulesDir)) {
    const itemPath = path.join(modulesDir, item);
    if (test('-L', itemPath)) {
      echo(`Deleting symlink ${item} in ${modulesDir}`);
      rm(itemPath);
    }
  }

  // Move the 'packages' subprojects up into this node_modules dir.
  const packagesDir = path.join(versionedOutputDir, appDir(platform), "packages");
  for (const item of ls(packagesDir)) {
    const destDir = path.join(modulesDir, item);
    echo(`Moving ${item} in to ${destDir}`);
    mv(path.join(packagesDir, item), destDir);
    const binDirPath = path.join(destDir, "node_modules", ".bin");
    if (fs.existsSync(binDirPath)) {
      rm('-rf', binDirPath);
    }
  }
}

function pruneNodeModules(versionedOutputDir, platform) {
  const prevDir = pwd();

  cd(path.join(versionedOutputDir, appDir(platform)));
  exec("modclean -n default:safe -r --ignore windows-swca");
  pruneSpecificNodeModules();

  cd(prevDir);
}

function pruneSpecificNodeModules() {
  [
    "node-sass/src",
    "node-sass/node_modules/node-gyp",
    "node-sass/vendor",
    "globule",
    "vue/src",
    "vue/dist/vue.esm.browser.js",
    "vue/dist/vue.esm.js",
    "vue/dist/vue.js",
    "vue/dist/vue.min.js",
    "vue/dist/vue.runtime.esm.js",
    "vue/dist/vue.runtime.js",
    "vue/dist/vue.runtime.min.js",
    ".bin"
  ].forEach( (subpath) => {
    const fullPath = path.join("node_modules", subpath);

    echo("Deleting " + fullPath);

    if (test('-d', fullPath)) {
      rm('-rf', fullPath);
    } else if (test('-f', fullPath)) {
        rm(fullPath);
    } else {
      echo("Warning: Unable to find path "+ fullPath);
    }
  });

}

function createOutputDirName({version, platform, arch}) {
  return "extraterm-" + version + "-" + platform + "-" + arch;
}

exports.createOutputDirName = createOutputDirName;

async function makePackage({ arch, platform, electronVersion, version, outputDir, replaceModuleDirs }) {
  log("");
  const SRC_DIR = "" + pwd();

  // Clean up the output dirs and files first.
  const versionedOutputDir = createOutputDirName({version, platform, arch});

  if (test('-d', versionedOutputDir)) {
    rm('-rf', versionedOutputDir);
  }

  const outputZip = path.join(outputDir, versionedOutputDir + ".zip");

  const packagerOptions = {
    arch: arch,
    dir: ".",
    platform: platform,
    version: electronVersion,
    ignore: ignoreFunc,
    name: platform === "darwin" ? "Extraterm" : "extraterm",
    overwrite: true,
    out: outputDir,
    prune: false
  };
  if (platform === "win32") {
    packagerOptions.icon = "extraterm/resources/logo/extraterm_small_logo.ico";
    packagerOptions.win32metadata = {
      FileDescription: "Extraterm",
      ProductName: "Extraterm",
      LegalCopyright: "(C) 2020 Simon Edwards"
    };
  } else if (platform === "darwin") {
    packagerOptions.icon = "extraterm/resources/logo/extraterm_small_logo.icns";
  }

  const appPath = await packager(packagerOptions);

  // Rename the output dir to a one with a version number in it.
  mv(appPath[0], path.join(outputDir, versionedOutputDir));

  const targetAppRootPath = platform === "darwin"
                    ? "Extraterm.app/Contents/Resources/app"
                    : "resources/app";
  const dirsDest = path.join(outputDir, versionedOutputDir, targetAppRootPath, "node_modules");
  const dirsSource = path.join("" + SRC_DIR,`build_scripts/node_modules-${platform}-${arch}`);

  if(replaceModuleDirs) {
    replaceDirs(dirsDest, dirsSource);
  }

  const thisCD = pwd();
  cd(outputDir);

  hoistSubprojectsModules(versionedOutputDir, platform);
  dependencyPruner.pruneDevDependencies(SRC_DIR, path.join(outputDir, versionedOutputDir, targetAppRootPath));
  pruneNodeModules(versionedOutputDir, platform);

  // Prune any unneeded node-sass binaries.
  pruneNodeSass(versionedOutputDir, arch, platform);
  pruneTwemoji(versionedOutputDir, platform);

  // Zip it up.
  log("Zipping up the package");

  mv(path.join(versionedOutputDir, "LICENSE"), path.join(versionedOutputDir, "LICENSE_electron.txt"));

  if (platform === "linux") {
    cp(path.join(SRC_DIR, "extraterm", "resources", "extraterm.desktop"), versionedOutputDir);
  }

  cp(path.join(SRC_DIR, "README.md"), versionedOutputDir);
  cp(path.join(SRC_DIR, "LICENSE.txt"), versionedOutputDir);

  const linkOption = process.platform === "win32" ? "" : " -y";
  exec(`zip ${linkOption} -r ${outputZip} ${versionedOutputDir}`);
  cd(thisCD);

  log("App bundle written to " + versionedOutputDir);
  return true;
}

function replaceDirs(targetDir, replacementsDir) {
  const replacements = ls(replacementsDir);
  replacements.forEach( (rDir) => {
    const targetSubDir = path.join(targetDir, rDir);
    if (test('-d', targetSubDir)) {
      rm('-r', targetSubDir);
    }
    cp('-r', path.join(replacementsDir, rDir), targetSubDir);
  });
}

exports.makePackage = makePackage;
<commit_msg>Correctly hoist the `extraterm-extension-api` package during package building<commit_after>/*
 * Copyright 2019 Simon Edwards <simon@simonzone.com>
 *
 * This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
 */
require('shelljs/global');
const path = require('path');
const fs = require('fs');
const packager = require('electron-packager');
const dependencyPruner = require('./dependency_pruner');
const log = console.log.bind(console);
const MODULE_VERSON = 69; // This version number also appears in thememanager.ts

const ignoreRegExp = [
  /^\/build_scripts\b/,
  /^\/extraterm-web-component-decorators\b/,
  /^\/extraterm-extension-api\b/,
  /^\/test\b/,
  /^\/build_tmp\b/,
  /^\/src\/typedocs\b/,
  /\.ts$/,
  /\.js\.map$/,
  /^\/\.git\//,
  /^\/docs\b/,
  /^\/resources\/extra_icons\b/,
  /^\/src\/test\b/,
  /^\/src\/testfiles\b/
];

const ignoreFunc = function ignoreFunc(filePath) {
  const result = ignoreRegExp.some( (exp) => exp.test(filePath));
  return result;
};

function appDir(platform) {
  return platform === "darwin" ? "Extraterm.app/Contents/Resources/app" : "resources/app";
}

function pruneNodeSass(versionedOutputDir, arch, platform) {
  const gutsDir = appDir(platform);
  const nodeSassVendorDir = path.join(versionedOutputDir, gutsDir, "node_modules/node-sass/vendor");

  rm('-rf', nodeSassVendorDir);

  const nodeSassBinaryDir = path.join(versionedOutputDir, gutsDir, "src/node-sass-binary");
  ["darwin-x64", "linux-ia32", "linux-x64", "win32-x64"].forEach( (name) => {
    if (name !== platform + "-" + arch) {
      rm('-rf', path.join(nodeSassBinaryDir, name + "-" + MODULE_VERSON));
    }
  });
}

function pruneTwemoji(versionedOutputDir, platform) {
  if (platform !== "linux") {
    const twemojiPath = path.join(versionedOutputDir, appDir(platform), "extraterm/resources/themes/default/fonts/Twemoji.ttf");
    rm(twemojiPath);
  }
}

function hoistSubprojectsModules(versionedOutputDir, platform) {
  const modulesDir = path.join(versionedOutputDir, appDir(platform), "node_modules");

  // Delete the symlinks.
  for (const item of ls(modulesDir)) {
    const itemPath = path.join(modulesDir, item);
    if (test('-L', itemPath)) {
      echo(`Deleting symlink ${item} in ${modulesDir}`);
      rm(itemPath);
    } else if (test('-d', itemPath) && itemPath.startsWith('@')) {
      for (const item2 of ls(path.join(modulesDir, item))) {
        const itemPath2 = path.join(modulesDir, item, item2);
        if (test('-L', itemPath2)) {
          echo(`Deleting deeper symlink ${path.join(item, item2)} in ${join(modulesDir, item)}`);
          rm(itemPath2);
        }
      }
    }
  }

  // Move the 'packages' subprojects up into this node_modules dir.
  const packagesDir = path.join(versionedOutputDir, appDir(platform), "packages");
  for (const item of ls(packagesDir)) {
    const packageJson = JSON.parse(fs.readFileSync(path.join(packagesDir, item, "package.json"), {encoding: "utf8"}));
    const destDir = path.join(modulesDir, packageJson.name);
    echo(`Moving ${item} in to ${destDir}`);
    mv(path.join(packagesDir, item), destDir);
    const binDirPath = path.join(destDir, "node_modules", ".bin");
    if (fs.existsSync(binDirPath)) {
      rm('-rf', binDirPath);
    }
  }
}

function pruneNodeModules(versionedOutputDir, platform) {
  const prevDir = pwd();

  cd(path.join(versionedOutputDir, appDir(platform)));
  exec("modclean -n default:safe -r --ignore windows-swca");
  pruneSpecificNodeModules();

  cd(prevDir);
}

function pruneSpecificNodeModules() {
  [
    "node-sass/src",
    "node-sass/node_modules/node-gyp",
    "node-sass/vendor",
    "globule",
    "vue/src",
    "vue/dist/vue.esm.browser.js",
    "vue/dist/vue.esm.js",
    "vue/dist/vue.js",
    "vue/dist/vue.min.js",
    "vue/dist/vue.runtime.esm.js",
    "vue/dist/vue.runtime.js",
    "vue/dist/vue.runtime.min.js",
    ".bin"
  ].forEach( (subpath) => {
    const fullPath = path.join("node_modules", subpath);

    echo("Deleting " + fullPath);

    if (test('-d', fullPath)) {
      rm('-rf', fullPath);
    } else if (test('-f', fullPath)) {
        rm(fullPath);
    } else {
      echo("Warning: Unable to find path "+ fullPath);
    }
  });

}

function createOutputDirName({version, platform, arch}) {
  return "extraterm-" + version + "-" + platform + "-" + arch;
}

exports.createOutputDirName = createOutputDirName;

async function makePackage({ arch, platform, electronVersion, version, outputDir, replaceModuleDirs }) {
  log("");
  const SRC_DIR = "" + pwd();

  // Clean up the output dirs and files first.
  const versionedOutputDir = createOutputDirName({version, platform, arch});

  if (test('-d', versionedOutputDir)) {
    rm('-rf', versionedOutputDir);
  }

  const outputZip = path.join(outputDir, versionedOutputDir + ".zip");

  const packagerOptions = {
    arch: arch,
    dir: ".",
    platform: platform,
    version: electronVersion,
    ignore: ignoreFunc,
    name: platform === "darwin" ? "Extraterm" : "extraterm",
    overwrite: true,
    out: outputDir,
    prune: false
  };
  if (platform === "win32") {
    packagerOptions.icon = "extraterm/resources/logo/extraterm_small_logo.ico";
    packagerOptions.win32metadata = {
      FileDescription: "Extraterm",
      ProductName: "Extraterm",
      LegalCopyright: "(C) 2020 Simon Edwards"
    };
  } else if (platform === "darwin") {
    packagerOptions.icon = "extraterm/resources/logo/extraterm_small_logo.icns";
  }

  const appPath = await packager(packagerOptions);

  // Rename the output dir to a one with a version number in it.
  mv(appPath[0], path.join(outputDir, versionedOutputDir));

  const targetAppRootPath = platform === "darwin"
                    ? "Extraterm.app/Contents/Resources/app"
                    : "resources/app";
  const dirsDest = path.join(outputDir, versionedOutputDir, targetAppRootPath, "node_modules");
  const dirsSource = path.join("" + SRC_DIR,`build_scripts/node_modules-${platform}-${arch}`);

  if(replaceModuleDirs) {
    replaceDirs(dirsDest, dirsSource);
  }

  const thisCD = pwd();
  cd(outputDir);

  hoistSubprojectsModules(versionedOutputDir, platform);
  dependencyPruner.pruneDevDependencies(SRC_DIR, path.join(outputDir, versionedOutputDir, targetAppRootPath));
  pruneNodeModules(versionedOutputDir, platform);

  // Prune any unneeded node-sass binaries.
  pruneNodeSass(versionedOutputDir, arch, platform);
  pruneTwemoji(versionedOutputDir, platform);

  // Zip it up.
  log("Zipping up the package");

  mv(path.join(versionedOutputDir, "LICENSE"), path.join(versionedOutputDir, "LICENSE_electron.txt"));

  if (platform === "linux") {
    cp(path.join(SRC_DIR, "extraterm", "resources", "extraterm.desktop"), versionedOutputDir);
  }

  cp(path.join(SRC_DIR, "README.md"), versionedOutputDir);
  cp(path.join(SRC_DIR, "LICENSE.txt"), versionedOutputDir);

  const linkOption = process.platform === "win32" ? "" : " -y";
  exec(`zip ${linkOption} -r ${outputZip} ${versionedOutputDir}`);
  cd(thisCD);

  log("App bundle written to " + versionedOutputDir);
  return true;
}

function replaceDirs(targetDir, replacementsDir) {
  const replacements = ls(replacementsDir);
  replacements.forEach( (rDir) => {
    const targetSubDir = path.join(targetDir, rDir);
    if (test('-d', targetSubDir)) {
      rm('-r', targetSubDir);
    }
    cp('-r', path.join(replacementsDir, rDir), targetSubDir);
  });
}

exports.makePackage = makePackage;
<|endoftext|>


<commit_before>var utils         = require('./utils.js');
var Administrator = require('./administrator.js');
var Client        = require('./client.js');

module.exports = Account;

function Account(createsend) {
    this.createsend = createsend;
}

Account.prototype = {
    addAdministrator: function (emailAddress, name, callback) {
        var createsend = this.createsend;
        createsend.post('admins', null, { 'EmailAddress': emailAddress, 'Name': name }, function (err, result) {
            if (err) { return callback(err); }
            callback(null, new Administrator(createsend, emailAddress, name));
        });
    },

    deleteAdministrator: function (emailAddress, callback) {
        new Administrator(this.createsend, emailAddress).delete(callback);
    },

    externalSession: function (request, callback) {
        this.createsend.put('externalsession.json', null, request, callback);
    },

    getAdministrators: function (callback) {
        var createsend = this.createsend;
        createsend.get('admins', null, null, function (err, admins) {
            if (err) { return callback(err); }

            for (var i = 0; i < admins.length; i++) {
                var admin = admins[i]
                admins[i] = new Administrator(createsend, admin.EmailAddress, admin.Name, admin.Status);
            }
            callback(null, admins);
        });
    },

    getAdministratorDetails: function (emailAddress, callback) {
        var administrator = new Administrator(this.createsend, emailAddress);
        administrator.getDetails(callback);
    },

    getBillingDetails: function (callback) {
        this.createsend.get('billingdetails.json', null, null, function (err, result) {
            if (err) { return callback(err); }

            callback(null, { credits: result.Credits });
        });
    },

    getClients: function (callback) {
        var createsend = this.createsend;
        createsend.get('clients.json', null, null, function (err, results) {
            if (err) { return callback(err); }

            var clients = [];
            for (var i = 0; i < results.length; i++) {
                clients.push(new Client(createsend, results[i].ClientID, results[i].Name));
            }
            callback(null, clients);
        });
    },

    getPrimaryContact: function (callback) {
        this.createsend.get('primarycontact.json', null, null, callback);
    },

    setPrimaryContact: function (emailAddress, callback) {
        this.createsend.put('primarycontact.json', { 'email': emailAddress }, null, callback);
    },

    updateAdministrator: function (emailAddress, newEmailAddress, newName, callback) {
        var administrator = new Administrator(this.createsend, emailAddress);
        administrator.update(newEmailAddress, newName, callback);
    }
}
<commit_msg>Use the JSON endpoint<commit_after>var utils         = require('./utils.js');
var Administrator = require('./administrator.js');
var Client        = require('./client.js');

module.exports = Account;

function Account(createsend) {
    this.createsend = createsend;
}

Account.prototype = {
    addAdministrator: function (emailAddress, name, callback) {
        var createsend = this.createsend;
        createsend.post('admins.json', null, { 'EmailAddress': emailAddress, 'Name': name }, function (err, result) {
            if (err) { return callback(err); }
            callback(null, new Administrator(createsend, emailAddress, name));
        });
    },

    deleteAdministrator: function (emailAddress, callback) {
        new Administrator(this.createsend, emailAddress).delete(callback);
    },

    externalSession: function (request, callback) {
        this.createsend.put('externalsession.json', null, request, callback);
    },

    getAdministrators: function (callback) {
        var createsend = this.createsend;
        createsend.get('admins.json', null, null, function (err, admins) {
            if (err) { return callback(err); }

            for (var i = 0; i < admins.length; i++) {
                var admin = admins[i]
                admins[i] = new Administrator(createsend, admin.EmailAddress, admin.Name, admin.Status);
            }
            callback(null, admins);
        });
    },

    getAdministratorDetails: function (emailAddress, callback) {
        var administrator = new Administrator(this.createsend, emailAddress);
        administrator.getDetails(callback);
    },

    getBillingDetails: function (callback) {
        this.createsend.get('billingdetails.json', null, null, function (err, result) {
            if (err) { return callback(err); }

            callback(null, { credits: result.Credits });
        });
    },

    getClients: function (callback) {
        var createsend = this.createsend;
        createsend.get('clients.json', null, null, function (err, results) {
            if (err) { return callback(err); }

            var clients = [];
            for (var i = 0; i < results.length; i++) {
                clients.push(new Client(createsend, results[i].ClientID, results[i].Name));
            }
            callback(null, clients);
        });
    },

    getPrimaryContact: function (callback) {
        this.createsend.get('primarycontact.json', null, null, callback);
    },

    setPrimaryContact: function (emailAddress, callback) {
        this.createsend.put('primarycontact.json', { 'email': emailAddress }, null, callback);
    },

    updateAdministrator: function (emailAddress, newEmailAddress, newName, callback) {
        var administrator = new Administrator(this.createsend, emailAddress);
        administrator.update(newEmailAddress, newName, callback);
    }
}
<|endoftext|>


<commit_before>/*
 * handlebars pattern engine for patternlab-node - v0.15.1 - 2015
 *
 * Geoffrey Pursell, Brian Muenzenmeyer, and the web community.
 * Licensed under the MIT license.
 *
 * Many thanks to Brad Frost and Dave Olsen for inspiration, encouragement, and advice.
 *
 */

(function () {
  "use strict";

  var Handlebars = require('handlebars');

  var engine_handlebars = {
    engine: Handlebars,
    engineName: 'handlebars',
    engineFileExtension: '.hbs',

    // partial expansion is only necessary for Mustache templates that have
    // style modifiers or pattern parameters (I think)
    expandPartials: false,

    // regexes, stored here so they're only compiled once
    // GTP warning: unchanged copypasta from mustache engine
    // findPartialsRE: /{{>\s*((?:\d+-[\w-]+\/)+(\d+-[\w-]+(\.\w+)?)|[A-Za-z0-9-]+)(\:[\w-]+)?(\(\s*\w+\s*:\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*")\))?\s*}}/g,
    findPartialsRE: /{{#?>\s*([\w-\/.]+)(?:.|\s+)*?}}/g,
    findPartialsWithStyleModifiersRE: /{{>([ ])?([\w\-\.\/~]+)(?!\()(\:[A-Za-z0-9-_|]+)+(?:(| )\(.*)?([ ])?}}/g,
    findPartialsWithPatternParametersRE: /{{>([ ])?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-_|]+)?(?:(| )\(.*)+([ ])?}}/g,
    findListItemsRE: /({{#( )?)(list(I|i)tems.)(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)( )?}}/g,

    // render it
    renderPattern: function renderPattern(template, data, partials) {
      if (partials) {
        Handlebars.registerPartial(partials);
      }
      var compiled = Handlebars.compile(template);
      return compiled(data);
    },

    registerPartial: function (oPattern) {
      Handlebars.registerPartial(oPattern.key, oPattern.template);
    },

    // find and return any {{> template-name }} within pattern
    findPartials: function findPartials(pattern) {
      var matches = pattern.template.match(this.findPartialsRE);
      return matches;
    },
    findPartialsWithStyleModifiers: function(pattern) {
      var matches = pattern.template.match(this.findPartialsWithStyleModifiersRE);
      return matches;
    },
    // returns any patterns that match {{> value(foo:"bar") }} or {{>
    // value:mod(foo:"bar") }} within the pattern
    findPartialsWithPatternParameters: function(pattern) {
      var matches = pattern.template.match(this.findPartialsWithPatternParametersRE);
      return matches;
    },
    findListItems: function(pattern) {
      var matches = pattern.template.match(this.findListItemsRE);
      return matches;
    },
    // given a pattern, and a partial string, tease out the "pattern key" and
    // return it.
    findPartialKey: function(pattern, partialString) {
      var partialKey = partialString.replace(this.findPartialsRE, '$1');
      return partialKey;
    }
  };

  module.exports = engine_handlebars;
})();
<commit_msg>fix handlebars engine's findPartialKey method signature to match new convention -- this method only needs a string<commit_after>/*
 * handlebars pattern engine for patternlab-node - v0.15.1 - 2015
 *
 * Geoffrey Pursell, Brian Muenzenmeyer, and the web community.
 * Licensed under the MIT license.
 *
 * Many thanks to Brad Frost and Dave Olsen for inspiration, encouragement, and advice.
 *
 */

(function () {
  "use strict";

  var Handlebars = require('handlebars');

  var engine_handlebars = {
    engine: Handlebars,
    engineName: 'handlebars',
    engineFileExtension: '.hbs',

    // partial expansion is only necessary for Mustache templates that have
    // style modifiers or pattern parameters (I think)
    expandPartials: false,

    // regexes, stored here so they're only compiled once
    // GTP warning: unchanged copypasta from mustache engine
    // findPartialsRE: /{{>\s*((?:\d+-[\w-]+\/)+(\d+-[\w-]+(\.\w+)?)|[A-Za-z0-9-]+)(\:[\w-]+)?(\(\s*\w+\s*:\s*(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*")\))?\s*}}/g,
    findPartialsRE: /{{#?>\s*([\w-\/.]+)(?:.|\s+)*?}}/g,
    findPartialsWithStyleModifiersRE: /{{>([ ])?([\w\-\.\/~]+)(?!\()(\:[A-Za-z0-9-_|]+)+(?:(| )\(.*)?([ ])?}}/g,
    findPartialsWithPatternParametersRE: /{{>([ ])?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-_|]+)?(?:(| )\(.*)+([ ])?}}/g,
    findListItemsRE: /({{#( )?)(list(I|i)tems.)(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)( )?}}/g,

    // render it
    renderPattern: function renderPattern(template, data, partials) {
      if (partials) {
        Handlebars.registerPartial(partials);
      }
      var compiled = Handlebars.compile(template);
      return compiled(data);
    },

    registerPartial: function (oPattern) {
      Handlebars.registerPartial(oPattern.key, oPattern.template);
    },

    // find and return any {{> template-name }} within pattern
    findPartials: function findPartials(pattern) {
      var matches = pattern.template.match(this.findPartialsRE);
      return matches;
    },
    findPartialsWithStyleModifiers: function(pattern) {
      var matches = pattern.template.match(this.findPartialsWithStyleModifiersRE);
      return matches;
    },
    // returns any patterns that match {{> value(foo:"bar") }} or {{>
    // value:mod(foo:"bar") }} within the pattern
    findPartialsWithPatternParameters: function(pattern) {
      var matches = pattern.template.match(this.findPartialsWithPatternParametersRE);
      return matches;
    },
    findListItems: function(pattern) {
      var matches = pattern.template.match(this.findListItemsRE);
      return matches;
    },
    // given a pattern, and a partial string, tease out the "pattern key" and
    // return it.
    findPartialKey: function(partialString) {
      var partialKey = partialString.replace(this.findPartialsRE, '$1');
      return partialKey;
    }
  };

  module.exports = engine_handlebars;
})();
<|endoftext|>


<commit_before>/*
Copyright (c) 2008-2013 Pivotal Labs

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
(function() {
  window.jasmine = jasmineRequire.core(jasmineRequire);
  jasmineRequire.html(jasmine);

  var env = jasmine.getEnv();

  var jasmineInterface = {
    describe: function(description, specDefinitions) {
      return env.describe(description, specDefinitions);
    },

    xdescribe: function(description, specDefinitions) {
      return env.xdescribe(description, specDefinitions);
    },

    it: function(desc, func) {
      return env.it(desc, func);
    },

    xit: function(desc, func) {
      return env.xit(desc, func);
    },

    beforeEach: function(beforeEachFunction) {
      return env.beforeEach(beforeEachFunction);
    },

    afterEach: function(afterEachFunction) {
      return env.afterEach(afterEachFunction);
    },

    expect: function(actual) {
      return env.expect(actual);
    },

    pending: function() {
      return env.pending();
    },

    spyOn: function(obj, methodName) {
      return env.spyOn(obj, methodName);
    },

    clock: env.clock,
    jsApiReporter: new jasmine.JsApiReporter({
      timer: new jasmine.Timer()
    })
  };

  if (typeof window == "undefined" && typeof exports == "object") {
    extend(exports, jasmineInterface);
  } else {
    extend(window, jasmineInterface);
  }

  jasmine.addCustomEqualityTester = function(tester) {
    env.addCustomEqualityTester(tester);
  };

  jasmine.addMatchers = function(matchers) {
    return env.addMatchers(matchers);
  };

  var queryString = new jasmine.QueryString({
    getWindowLocation: function() { return window.location; }
  });

  // TODO: move all of catching to raise so we don't break our brains
  var catchingExceptions = queryString.getParam("catch");
  env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);

  var htmlReporter = new jasmine.HtmlReporter({
    env: env,
    queryString: queryString,
    onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
    getContainer: function() { return document.body; },
    createElement: function() { return document.createElement.apply(document, arguments); },
    createTextNode: function() { return document.createTextNode.apply(document, arguments); },
    timer: new jasmine.Timer()
  });

  env.addReporter(jasmineInterface.jsApiReporter);
  env.addReporter(htmlReporter);

  var specFilter = new jasmine.HtmlSpecFilter({
    filterString: function() { return queryString.getParam("spec"); }
  });

  env.specFilter = function(spec) {
    return specFilter.matches(spec.getFullName());
  };

  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    htmlReporter.initialize();
    env.execute();
  };

  function extend(destination, source) {
    for (var property in source) destination[property] = source[property];
    return destination;
  }

}());
<commit_msg>Continuing boot change with docs<commit_after>/*
Copyright (c) 2008-2013 Pivotal Labs

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
 Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.

 If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.

 The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.

 [jasmine-gem]: http://github.com/pivotal/jasmine-gem
 */

(function() {

  /**
   * ## Require & Instantiate
   *
   * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
   */
  window.jasmine = jasmineRequire.core(jasmineRequire);

  /**
   * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
   */
  jasmineRequire.html(jasmine);

  /**
   * Create the Jasmine environment. This is used to run all specs in a project.
   */
  var env = jasmine.getEnv();

  /**
   * ## The Global Interface
   *
   * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
   */
  var jasmineInterface = {
    describe: function(description, specDefinitions) {
      return env.describe(description, specDefinitions);
    },

    xdescribe: function(description, specDefinitions) {
      return env.xdescribe(description, specDefinitions);
    },

    it: function(desc, func) {
      return env.it(desc, func);
    },

    xit: function(desc, func) {
      return env.xit(desc, func);
    },

    beforeEach: function(beforeEachFunction) {
      return env.beforeEach(beforeEachFunction);
    },

    afterEach: function(afterEachFunction) {
      return env.afterEach(afterEachFunction);
    },

    expect: function(actual) {
      return env.expect(actual);
    },

    pending: function() {
      return env.pending();
    },

    addMatchers: function(matchers) {
      return env.addMatchers(matchers);
    },

    spyOn: function(obj, methodName) {
      return env.spyOn(obj, methodName);
    },

    clock: env.clock,

    addCustomEqualityTester: function(tester) {
      env.addCustomEqualityTester(tester);
    },

    jsApiReporter: new jasmine.JsApiReporter({
      timer: new jasmine.Timer()
    })
  };

  /**
   * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
   */
  if (typeof window == "undefined" && typeof exports == "object") {
    extend(exports, jasmineInterface);
  } else {
    extend(window, jasmineInterface);
  }

  /**
   * Expose the interface for adding custom equality testers.
   */
  jasmine.addCustomEqualityTester = function(tester) {
    env.addCustomEqualityTester(tester);
  };

  /**
   * Expose the interface for adding custom expectation matchers
   */
  jasmine.addMatchers = function(matchers) {
    return env.addMatchers(matchers);
  };

  /**
   * ## Runner Parameters
   *
   * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
   */

  var queryString = new jasmine.QueryString({
    getWindowLocation: function() { return window.location; }
  });

  var catchingExceptions = queryString.getParam("catch");
  env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);

  /**
   * ## Reporters
   * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
   */
  var htmlReporter = new jasmine.HtmlReporter({
    env: env,
    queryString: queryString,
    onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
    getContainer: function() { return document.body; },
    createElement: function() { return document.createElement.apply(document, arguments); },
    createTextNode: function() { return document.createTextNode.apply(document, arguments); },
    timer: new jasmine.Timer()
  });

  /**
   * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results  from JavaScript.
   */
  env.addReporter(jasmineInterface.jsApiReporter);
  env.addReporter(htmlReporter);

  /**
   * Filter which specs will be run by matching the start of the full name against the `spec` query param.
   */
  var specFilter = new jasmine.HtmlSpecFilter({
    filterString: function() { return queryString.getParam("spec"); }
  });

  env.specFilter = function(spec) {
    return specFilter.matches(spec.getFullName());
  };

  /**
   * ## Execution
   *
   * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
   */
  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    htmlReporter.initialize();
    env.execute();
  };

  /**
   * Helper function for readability above.
   */
  function extend(destination, source) {
    for (var property in source) destination[property] = source[property];
    return destination;
  }

}());<|endoftext|>


<commit_before>const fs = require("fs");
const http = require("http");
const child_process = require("child_process");
const createHandler = require("github-webhook-handler");
const handler = createHandler({path: "/", secret: global.config.webhook_secret});

const server = http.createServer((req, res) => {
    handler(req, res, (err) => {
        res.statusCode = 404;
        res.end("No such file or directory.");
    });
}).listen(7777);

handler.on("release", (evt) => {
    let newVersion = evt.payload.release.tag_name;
    //Asegurarnos de que el bot esta `ready`
    if(global.bot.readyAt.getTime() < new Date().getTime()) {

        global.bot.channels.get("272393533040885761").sendMessage("Actualizando a la version " + newVersion);
    }
    //cerrar el servidor http para que el nuevo bot pueda escuchar el mismo puerto.
    server.close();

    //Clonar la nueva version a una carpeta paralela
    child_process.execSync("git clone https:\/\/github.com/mcmacker4/darkbot2 ../" + newVersion);
    process.chdir("../" + newVersion)
    //Instalar dependencias
    child_process.execSync("npm install");

    //Abrir archivo para el log
    const stdio = fs.openSync("out.log", "a");

    //Destruir el bot actual y ejecutar el nuevo.
    child_process.spawn("node", ["main.js", newVersion, global.config.version], { detached: true, stdio: ["ignore", stdio, stdio] });
    process.exit();
});

global.bot.on("ready", () => {
    global.bot.user.setGame("version " + global.config.version);
    if(global.config.oldVersion) {
        try {
            child_process.execSync()
        } catch (err) {
            console.log("Error al eliminar version antigua: " + err.message);
        }
    }
});
<commit_msg>Oops v2<commit_after>const fs = require("fs");
const http = require("http");
const child_process = require("child_process");
const createHandler = require("github-webhook-handler");
const handler = createHandler({path: "/", secret: global.config.webhook_secret});

const server = http.createServer((req, res) => {
    handler(req, res, (err) => {
        res.statusCode = 404;
        res.end("No such file or directory.");
    });
}).listen(7777);

handler.on("release", (evt) => {
    let newVersion = evt.payload.release.tag_name;
    //Asegurarnos de que el bot esta `ready`
    if(global.bot.readyAt.getTime() < new Date().getTime()) {

        global.bot.channels.get("272393533040885761").sendMessage("Actualizando a la version " + newVersion);
    }
    //cerrar el servidor http para que el nuevo bot pueda escuchar el mismo puerto.
    server.close();

    //Clonar la nueva version a una carpeta paralela
    child_process.execSync("git clone https:\/\/github.com/mcmacker4/darkbot2 ../" + newVersion);
    process.chdir("../" + newVersion)
    //Instalar dependencias
    child_process.execSync("npm install");

    //Abrir archivo para el log
    const stdio = fs.openSync("out.log", "a");

    //Destruir el bot actual y ejecutar el nuevo.
    child_process.spawn("node", ["main.js", newVersion, global.config.version], { detached: true, stdio: ["ignore", stdio, stdio] });
    process.exit();
});

global.bot.on("ready", () => {
    global.bot.user.setGame("version " + global.config.version);
    if(global.config.oldVersion) {
        try {
            child_process.execSync("rm -rf ../" + global.config.oldVersion);
        } catch (err) {
            console.log("Error al eliminar version antigua: " + err.message);
        }
    }
});
<|endoftext|>


<commit_before>"use strict";

var $ = require('jquery'),
    L = require('leaflet');

var zoom = {
    NEIGHBORHOOD: 16
};

module.exports = {
    create: create
};

function create(options) {
    options = $.extend({
        domId: 'map'
    }, options);

    var map = L.map(options.domId, {
            zoomControl: false
        }),
        zoomControl = L.control.zoom({position: 'bottomleft'}).addTo(map),
        $controlsContainer = $(zoomControl.getContainer());

    initBaseMap(map);

    if (options.geolocation && navigator.geolocation) {
        initGeolocation($controlsContainer, map);
    }

    // New York City bounds from http://www.mapdevelopers.com/geocode_bounding_box.php
    map.fitBounds([
        [40.495996, -74.259088],
        [40.915256, -73.700272]
    ]);

    return map;
}

function initBaseMap(map) {
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        osmAttrib = 'Map data © OpenStreetMap contributors',
        osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});

    map.addLayer(osm);
}

function initGeolocation($controlsContainer, map) {
    var $button = $('X')
    $controlsContainer.prepend($button);

    $button.on('click', function () {
        navigator.geolocation.getCurrentPosition(showPosition, showError);
    });

    function showPosition(position) {
        var center = L.latLng(position.coords.latitude, position.coords.longitude);
        map.setView(center, zoom.NEIGHBORHOOD);
    }

    function showError() {
        alert('Unable to show your location.');
    }

}<commit_msg>Fix lint<commit_after>"use strict";

var $ = require('jquery'),
    L = require('leaflet');

var zoom = {
    NEIGHBORHOOD: 16
};

module.exports = {
    create: create
};

function create(options) {
    options = $.extend({
        domId: 'map'
    }, options);

    var map = L.map(options.domId, {
            zoomControl: false
        }),
        zoomControl = L.control.zoom({position: 'bottomleft'}).addTo(map),
        $controlsContainer = $(zoomControl.getContainer());

    initBaseMap(map);

    if (options.geolocation && navigator.geolocation) {
        initGeolocation($controlsContainer, map);
    }

    // New York City bounds from http://www.mapdevelopers.com/geocode_bounding_box.php
    map.fitBounds([
        [40.495996, -74.259088],
        [40.915256, -73.700272]
    ]);

    return map;
}

function initBaseMap(map) {
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        osmAttrib = 'Map data © OpenStreetMap contributors',
        osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});

    map.addLayer(osm);
}

function initGeolocation($controlsContainer, map) {
    var $button = $('X');
    $controlsContainer.prepend($button);

    $button.on('click', function () {
        navigator.geolocation.getCurrentPosition(showPosition, showError);
    });

    function showPosition(position) {
        var center = L.latLng(position.coords.latitude, position.coords.longitude);
        map.setView(center, zoom.NEIGHBORHOOD);
    }

    function showError() {
        window.alert('Unable to show your location.');
    }

}<|endoftext|>