<commit_before>goog.provide('ol.MapRenderer');
goog.provide('ol.MapRendererProperty');

goog.require('goog.array');
goog.require('goog.events');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('ol.Array');
goog.require('ol.Camera');
goog.require('ol.CameraProperty');
goog.require('ol.LayerRenderer');
goog.require('ol.Object');
goog.require('ol.Projection');

/**
 * @enum {string}
 */
ol.MapRendererProperty = {
  CAMERA: 'camera',
  LAYERS: 'layers',
  PROJECTION: 'projection'
};

/**
 * @constructor
 * @extends {ol.Object}
 * @param {HTMLDivElement} target Target.
 * @param {Object=} opt_values Values.
 */
ol.MapRenderer = function(target, opt_values) {

  goog.base(this);

  /**
   * @private
   * @type {HTMLDivElement}
   */
  this.target_ = target;

  /**
   * @private
   * @type {goog.math.Size}
   */
  this.size_ = new goog.math.Size(target.clientWidth, target.clientHeight);

  /**
   * @private
   * @type {Array.<number>}
   */
  this.cameraListenerKeys_ = null;

  /**
   * @private
   * @type {Array.<number>}
   */
  this.layersListenerKeys_ = null;

  /**
   * @private
   * @type {Object.<number, ol.LayerRenderer>}
   */
  this.layerRenderers_ = {};

  goog.events.listen(target, goog.events.EventType.RESIZE,
      this.handleTargetResize, false, this);

  goog.events.listen(
      this, ol.Object.getChangedEventType(ol.MapRendererProperty.CAMERA),
      this.handleCameraChanged, false, this);

  goog.events.listen(
      this, ol.Object.getChangedEventType(ol.MapRendererProperty.LAYERS),
      this.handleLayersChanged, false, this);

  if (goog.isDef(opt_values)) {
    this.setValues(opt_values);
  }

};
goog.inherits(ol.MapRenderer, ol.Object);

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 * @return {ol.LayerRenderer} layerRenderer Layer renderer.
 */
ol.MapRenderer.prototype.createLayerRenderer = goog.abstractMethod;

/**
 * @protected
 * @param {function(this: T, ol.LayerRenderer)} f Function.
 * @param {T=} opt_obj The object to be used for the value of 'this' within f.
 * @template T
 */
ol.MapRenderer.prototype.forEachLayerRenderer = function(f, opt_obj) {
  var layers = this.getLayers();
  if (goog.isDefAndNotNull(layers)) {
    layers.forEach(function(layer) {
      var key = goog.getUid(layer);
      var layerRenderer = this.layerRenderers_[key];
      f.call(opt_obj, layerRenderer);
    }, this);
  }
};

/**
 * @return {ol.Camera} Camera.
 */
ol.MapRenderer.prototype.getCamera = function() {
  return /** @type {ol.Camera} */ (this.get(ol.MapRendererProperty.CAMERA));
};

/**
 * @return {ol.Array} Layers.
 */
ol.MapRenderer.prototype.getLayers = function() {
  return /** @type {ol.Array} */ (this.get(ol.MapRendererProperty.LAYERS));
};

/**
 * @return {ol.Projection} Projection.
 */
ol.MapRenderer.prototype.getProjection = function() {
  return /** @type {ol.Projection} */ (
      this.get(ol.MapRendererProperty.PROJECTION));
};

/**
 * @protected
 * @return {goog.math.Size} Size.
 */
ol.MapRenderer.prototype.getSize = function() {
  return this.size_;
};

/**
 * @return {HTMLDivElement} Target.
 */
ol.MapRenderer.prototype.getTarget = function() {
  return this.target_;
};

/**
 * @protected
 */
ol.MapRenderer.prototype.handleCameraChanged = function() {
  if (!goog.isNull(this.cameraListenerKeys_)) {
    goog.array.forEach(this.cameraListenerKeys_, goog.events.unlistenByKey);
    this.cameraListenerKeys_ = null;
  }
  var camera = this.getCamera();
  if (!goog.isNull(camera)) {
    this.cameraListenerKeys_ = goog.array.map(
        goog.object.getValues(ol.CameraProperty),
        function(cameraProperty) {
          return goog.events.listen(camera, cameraProperty,
              this.handleCameraPropertyChanged, false, this);
        });
  }
};

/**
 * @protected
 */
ol.MapRenderer.prototype.handleCameraPropertyChanged = function() {
};

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 */
ol.MapRenderer.prototype.handleLayerAdd = function(layer) {
  var key = goog.getUid(layer);
  var layerRenderer = this.createLayerRenderer(layer);
  this.layerRenderers_[key] = layerRenderer;
};

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 */
ol.MapRenderer.prototype.handleLayerRemove = function(layer) {
  var key = goog.getUid(layer);
  goog.asserts.assert(key in this.layerRenderers_);
  var layerRenderer = this.layerRenderers_[key];
  delete this.layerRenderers_[key];
  goog.dispose(layerRenderer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersInsertAt = function(event) {
  var layers = /** @type {ol.Array} */ (event.target);
  var layer = /** @type {ol.Layer} */ layers.getAt(event.index);
  this.handleLayerAdd(layer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersRemoveAt = function(event) {
  var layer = /** @type {ol.Layer} */ (event.prev);
  this.handleLayerRemove(layer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersSetAt = function(event) {
  var prevLayer = /** @type {ol.Layer} */ (event.prev);
  this.handleLayerRemove(prevLayer);
  var layers = /** @type {ol.Array} */ (event.target);
  var layer = /** @type {ol.Layer} */ layers.getAt(event.index);
  this.handleLayerAdd(layer);
};

/**
 */
ol.MapRenderer.prototype.handleLayersChanged = function() {
  if (!goog.isNull(this.layersListenerKeys_)) {
    goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
    this.layersListenerKeys_ = null;
  }
  var layers = this.getLayers();
  if (!goog.isNull(layers)) {
    this.layersListenerKeys_ = [
      goog.events.listen(layers, ol.ArrayEventType.INSERT_AT,
          this.handleLayersInsertAt, false, this),
      goog.events.listen(layers, ol.ArrayEventType.REMOVE_AT,
          this.handleLayersRemoveAt, false, this),
      goog.events.listen(layers, ol.ArrayEventType.SET_AT,
          this.handleLayersSetAt, false, this)
    ];
  }
};

/**
 * @param {goog.events.Event} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleTargetResize = function(event) {
  goog.asserts.assert(event.target == this.target_);
  this.size_.width = this.target_.clientWidth;
  this.size_.height = this.target_.clientHeight;
};

/**
 * @param {ol.Camera} camera Camera.
 */
ol.MapRenderer.prototype.setCamera = function(camera) {
  this.set(ol.MapRendererProperty.CAMERA, camera);
};

/**
 * @param {ol.Array} layers Layers.
 */
ol.MapRenderer.prototype.setLayers = function(layers) {
  this.set(ol.MapRendererProperty.LAYERS, layers);
};

/**
 * @param {ol.Projection} projection Projection.
 */
ol.MapRenderer.prototype.setProjection = function(projection) {
  this.set(ol.MapRendererProperty.PROJECTION, projection);
};
<commit_msg>Handle undefined properties<commit_after>goog.provide('ol.MapRenderer');
goog.provide('ol.MapRendererProperty');

goog.require('goog.array');
goog.require('goog.events');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('ol.Array');
goog.require('ol.Camera');
goog.require('ol.CameraProperty');
goog.require('ol.LayerRenderer');
goog.require('ol.Object');
goog.require('ol.Projection');

/**
 * @enum {string}
 */
ol.MapRendererProperty = {
  CAMERA: 'camera',
  LAYERS: 'layers',
  PROJECTION: 'projection'
};

/**
 * @constructor
 * @extends {ol.Object}
 * @param {HTMLDivElement} target Target.
 * @param {Object=} opt_values Values.
 */
ol.MapRenderer = function(target, opt_values) {

  goog.base(this);

  /**
   * @private
   * @type {HTMLDivElement}
   */
  this.target_ = target;

  /**
   * @private
   * @type {goog.math.Size}
   */
  this.size_ = new goog.math.Size(target.clientWidth, target.clientHeight);

  /**
   * @private
   * @type {Array.<number>}
   */
  this.cameraListenerKeys_ = null;

  /**
   * @private
   * @type {Array.<number>}
   */
  this.layersListenerKeys_ = null;

  /**
   * @private
   * @type {Object.<number, ol.LayerRenderer>}
   */
  this.layerRenderers_ = {};

  goog.events.listen(target, goog.events.EventType.RESIZE,
      this.handleTargetResize, false, this);

  goog.events.listen(
      this, ol.Object.getChangedEventType(ol.MapRendererProperty.CAMERA),
      this.handleCameraChanged, false, this);

  goog.events.listen(
      this, ol.Object.getChangedEventType(ol.MapRendererProperty.LAYERS),
      this.handleLayersChanged, false, this);

  if (goog.isDef(opt_values)) {
    this.setValues(opt_values);
  }

};
goog.inherits(ol.MapRenderer, ol.Object);

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 * @return {ol.LayerRenderer} layerRenderer Layer renderer.
 */
ol.MapRenderer.prototype.createLayerRenderer = goog.abstractMethod;

/**
 * @protected
 * @param {function(this: T, ol.LayerRenderer)} f Function.
 * @param {T=} opt_obj The object to be used for the value of 'this' within f.
 * @template T
 */
ol.MapRenderer.prototype.forEachLayerRenderer = function(f, opt_obj) {
  var layers = this.getLayers();
  if (goog.isDefAndNotNull(layers)) {
    layers.forEach(function(layer) {
      var key = goog.getUid(layer);
      var layerRenderer = this.layerRenderers_[key];
      f.call(opt_obj, layerRenderer);
    }, this);
  }
};

/**
 * @return {ol.Camera} Camera.
 */
ol.MapRenderer.prototype.getCamera = function() {
  return /** @type {ol.Camera} */ (this.get(ol.MapRendererProperty.CAMERA));
};

/**
 * @return {ol.Array} Layers.
 */
ol.MapRenderer.prototype.getLayers = function() {
  return /** @type {ol.Array} */ (this.get(ol.MapRendererProperty.LAYERS));
};

/**
 * @return {ol.Projection} Projection.
 */
ol.MapRenderer.prototype.getProjection = function() {
  return /** @type {ol.Projection} */ (
      this.get(ol.MapRendererProperty.PROJECTION));
};

/**
 * @protected
 * @return {goog.math.Size} Size.
 */
ol.MapRenderer.prototype.getSize = function() {
  return this.size_;
};

/**
 * @return {HTMLDivElement} Target.
 */
ol.MapRenderer.prototype.getTarget = function() {
  return this.target_;
};

/**
 * @protected
 */
ol.MapRenderer.prototype.handleCameraChanged = function() {
  if (!goog.isNull(this.cameraListenerKeys_)) {
    goog.array.forEach(this.cameraListenerKeys_, goog.events.unlistenByKey);
    this.cameraListenerKeys_ = null;
  }
  var camera = this.getCamera();
  if (goog.isDefAndNotNull(camera)) {
    this.cameraListenerKeys_ = goog.array.map(
        goog.object.getValues(ol.CameraProperty),
        function(cameraProperty) {
          return goog.events.listen(camera, cameraProperty,
              this.handleCameraPropertyChanged, false, this);
        },
        this);
  }
};

/**
 * @protected
 */
ol.MapRenderer.prototype.handleCameraPropertyChanged = function() {
};

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 */
ol.MapRenderer.prototype.handleLayerAdd = function(layer) {
  var key = goog.getUid(layer);
  var layerRenderer = this.createLayerRenderer(layer);
  this.layerRenderers_[key] = layerRenderer;
};

/**
 * @param {ol.Layer} layer Layer.
 * @protected
 */
ol.MapRenderer.prototype.handleLayerRemove = function(layer) {
  var key = goog.getUid(layer);
  goog.asserts.assert(key in this.layerRenderers_);
  var layerRenderer = this.layerRenderers_[key];
  delete this.layerRenderers_[key];
  goog.dispose(layerRenderer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersInsertAt = function(event) {
  var layers = /** @type {ol.Array} */ (event.target);
  var layer = /** @type {ol.Layer} */ layers.getAt(event.index);
  this.handleLayerAdd(layer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersRemoveAt = function(event) {
  var layer = /** @type {ol.Layer} */ (event.prev);
  this.handleLayerRemove(layer);
};

/**
 * @param {ol.ArrayEvent} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleLayersSetAt = function(event) {
  var prevLayer = /** @type {ol.Layer} */ (event.prev);
  this.handleLayerRemove(prevLayer);
  var layers = /** @type {ol.Array} */ (event.target);
  var layer = /** @type {ol.Layer} */ layers.getAt(event.index);
  this.handleLayerAdd(layer);
};

/**
 */
ol.MapRenderer.prototype.handleLayersChanged = function() {
  if (!goog.isNull(this.layersListenerKeys_)) {
    goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
    this.layersListenerKeys_ = null;
  }
  var layers = this.getLayers();
  if (goog.isDefAndNotNull(layers)) {
    this.layersListenerKeys_ = [
      goog.events.listen(layers, ol.ArrayEventType.INSERT_AT,
          this.handleLayersInsertAt, false, this),
      goog.events.listen(layers, ol.ArrayEventType.REMOVE_AT,
          this.handleLayersRemoveAt, false, this),
      goog.events.listen(layers, ol.ArrayEventType.SET_AT,
          this.handleLayersSetAt, false, this)
    ];
  }
};

/**
 * @param {goog.events.Event} event Event.
 * @protected
 */
ol.MapRenderer.prototype.handleTargetResize = function(event) {
  goog.asserts.assert(event.target == this.target_);
  this.size_.width = this.target_.clientWidth;
  this.size_.height = this.target_.clientHeight;
};

/**
 * @param {ol.Camera} camera Camera.
 */
ol.MapRenderer.prototype.setCamera = function(camera) {
  this.set(ol.MapRendererProperty.CAMERA, camera);
};

/**
 * @param {ol.Array} layers Layers.
 */
ol.MapRenderer.prototype.setLayers = function(layers) {
  this.set(ol.MapRendererProperty.LAYERS, layers);
};

/**
 * @param {ol.Projection} projection Projection.
 */
ol.MapRenderer.prototype.setProjection = function(projection) {
  this.set(ol.MapRendererProperty.PROJECTION, projection);
};
<|endoftext|>


<commit_before>/**
 * @module ol/source/IIIF
 */

import {DEFAULT_TILE_SIZE} from '../tilegrid/common.js';
import {getTopLeft} from '../extent.js';
import {CustomTile} from './Zoomify.js';
import {Versions} from '../format/IIIFInfo.js';
import {assert} from '../asserts.js';
import TileGrid from '../tilegrid/TileGrid.js';
import TileImage from './TileImage.js';

/**
 * @typedef {Object} Options
 * @property {import("./Source.js").AttributionLike} [attributions] Attributions.
 * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.
 * @property {number} [cacheSize]
 * @property {null|string} [crossOrigin]
 * @property {import("../proj.js").ProjectionLike} [projection]
 * @property {number} [tilePixelRatio]
 * @property {number} [reprojectionErrorThreshold=0.5]
 * @property {string} [url] Base URL of the IIIF Image service.
 * This shoulf be the same as the IIIF Image @id.
 * @property {import("../size.js").Size} [size] Size of the image [width, height].
 * @property {import("../size.js").Size[]} [sizes] Supported scaled image sizes.
 * Content of the IIIF info.json 'sizes' property, but as array of Size objects.
 * @property {import("../extent.js").Extent} [extent=[0, -height, width, 0]]
 * @property {number} [transition]
 * @property {number|import("../size.js").Size} [tileSize] Tile size.
 * Same tile size is used for all zoom levels. If tile size is a number,
 * a square tile is assumed. If the IIIF image service supports arbitrary
 * tiling (sizeByH, sizeByW or sizeByPct as well as regionByPx and regionByPct
 * are supported), the default tilesize is 256.
 * @property {boolean} [wrapX=false]
 */

function formatPercentage(percentage) {
  return percentage.toLocaleString('en', {maximumFractionDigits: 10});
}

/**
 * @classdesc
 * Layer source for tile data in IIIF format.
 * @api
 */
class IIIF extends TileImage {

  constructor(opt_options) {

    const options = opt_options || {};

    let baseUrl = options.url || '';
    baseUrl = baseUrl + (baseUrl.lastIndexOf('/') === baseUrl.length - 1 || baseUrl === '' ? '' : '/');
    const version = options.version || Versions.VERSION2;
    const sizes = options.sizes || [];
    const size = options.size;
    assert(size != undefined && Array.isArray(size) && size.length == 2 &&
      !isNaN(size[0]) && size[0] > 0 && !isNaN(size[1] && size[1] > 0), 60);
    const width = size[0];
    const height = size[1];
    const tileSize = options.tileSize;
    const format = options.format || 'jpg';
    const quality = options.quality || (options.version == Versions.VERSION1 ? 'native' : 'default');
    let resolutions = options.resolutions || [];
    const features = options.features || [];
    const extent = options.extent || [0, -height, width, 0];

    const supportsListedSizes = sizes != undefined && Array.isArray(sizes) && sizes.length > 0;
    const supportsListedTiles = tileSize != undefined && (Number.isInteger(tileSize) && tileSize > 0 || Array.isArray(tileSize) && tileSize.length > 0);
    const supportsArbitraryTiling = features != undefined && Array.isArray(features) &&
      (features.includes('regionByPx') || features.includes('regionByPct')) &&
      (features.includes('sizeByWh') || features.includes('sizeByH') ||
      features.includes('sizeByW') || features.includes('sizeByPct'));

    let tileWidth,
        tileHeight,
        maxZoom;

    resolutions.sort(function(a, b) {
      return b - a;
    });

    if (supportsListedTiles || supportsArbitraryTiling) {
      if (tileSize != undefined) {
        if (Number.isInteger(tileSize) && tileSize > 0) {
          tileWidth = tileSize;
          tileHeight = tileSize;
        } else if (Array.isArray(tileSize) && tileSize.length > 0) {
          if (tileSize.length == 1 || tileSize[1] == undefined && Number.isInteger(tileSize[0])) {
            tileWidth = tileSize[0];
            tileHeight = tileSize[0];
          }
          if (tileSize.length == 2) {
            if (Number.isInteger(tileSize[0]) && Number.isInteger(tileSize[1])) {
              tileWidth = tileSize[0];
              tileHeight = tileSize[1];
            } else if (tileSize[0] == undefined && Number.isInteger(tileSize[1])) {
              tileWidth = tileSize[1];
              tileHeight = tileSize[1];
            }
          }
        }
      }
      if (tileWidth === undefined || tileHeight === undefined) {
        tileWidth = DEFAULT_TILE_SIZE;
        tileHeight = DEFAULT_TILE_SIZE;
      }
      if (resolutions.length == 0) {
        maxZoom = Math.max(
          Math.ceil(Math.log(width / tileWidth) / Math.LN2),
          Math.ceil(Math.log(height / tileHeight) / Math.LN2)
        );
        for (let i = maxZoom; i >= 0; i--) {
          resolutions.push(Math.pow(2, i));
        }
      } else {
        const maxScaleFactor = Math.max([...resolutions]);
        // TODO maxScaleFactor might not be a power to 2
        maxZoom = Math.round(Math.log(maxScaleFactor) / Math.LN2);
      }
    } else {
      // No tile support.
      tileWidth = width;
      tileHeight = height;
      resolutions = [];
      if (supportsListedSizes) {
        /*
         * 'sizes' provided. Use full region in different resolutions. Every
         * resolution has only one tile.
         */
        sizes.sort(function(a, b) {
          return a[0] - b[0];
        });
        for (let i = 0; i < sizes.length; i++) {
          const resolution = width / sizes[i][0];
          resolutions.push(resolution);
          maxZoom = i;
        }
      } else {
        // No useful image information at all. Try pseudo tile with full image.
        resolutions.push(1);
        sizes.push([width, height]);
        maxZoom = 0;
      }
    }

    const tileGrid = new TileGrid({
      tileSize: [tileWidth, tileHeight],
      extent: extent,
      origin: getTopLeft(extent),
      resolutions: resolutions
    });

    const tileUrlFunction = function(tileCoord, pixelRatio, projection) {
      let regionParam,
          sizeParam;
      const zoom = tileCoord[0];
      if (maxZoom < zoom) {
        return;
      }
      const tileX = tileCoord[1],
          tileY = tileCoord[2],
          scale = resolutions[zoom];
      if (tileX < 0 || Math.ceil(width / scale / tileWidth) <= tileX ||
      tileY < 0 || Math.ceil(height / scale / tileHeight) <= tileY) {
        return;
      }
      if (supportsArbitraryTiling || supportsListedTiles) {
        const regionX = tileX * tileWidth * scale,
            regionY = tileY * tileHeight * scale;
        let regionW = tileWidth * scale,
            regionH = tileHeight * scale,
            sizeW = tileWidth,
            sizeH = tileHeight;
        if (regionX + regionW > width) {
          regionW = width - regionX;
        }
        if (regionY + regionH > height) {
          regionH = height - regionY;
        }
        if (regionX + tileWidth * scale > width) {
          sizeW = Math.floor((width - regionX + scale - 1) / scale);
        }
        if (regionY + tileHeight * scale > height) {
          sizeH = Math.floor((height - regionY + scale - 1) / scale);
        }
        const sizeHBySizeW = Math.round(sizeW / regionW * regionH),
            sizeWBySizeH = Math.round(sizeH / regionH * regionW),
            preferSizeByH = (sizeHBySizeW > sizeH) && (sizeW == sizeWBySizeH);
        if (regionX == 0 && regionW == width && regionY == 0 && regionH == height) {
          // canonical full image region parameter is 'full', not 'x,y,w,h'
          regionParam = 'full';
        } else if (!supportsArbitraryTiling || features.includes('regionByPx')) {
          regionParam = regionX + ',' + regionY + ',' + regionW + ',' + regionH;
        } else if (features.includes('regionByPct')) {
          const pctX = formatPercentage(regionX / width * 100),
              pctY = formatPercentage(regionY / height * 100),
              pctW = formatPercentage(regionW / width * 100),
              pctH = formatPercentage(regionH / height * 100);
          regionParam = 'pct:' + pctX + ',' + pctY + ',' + pctW + ',' + pctH;
        }
        if (version == Versions.VERSION3 && (!supportsArbitraryTiling || features.includes('sizeByWh'))) {
          sizeParam = sizeW + ',' + sizeH;
        } else if (!supportsArbitraryTiling || features.includes('sizeByW') && (!preferSizeByH || !(features.includes('sizeByH')))) {
          sizeParam = sizeW + ',';
        } else if (features.includes('sizeByH')) {
          sizeParam = ',' + sizeH;
        } else if (features.includes('sizeByWh')) {
          sizeParam = sizeW + ',' + sizeH;
        } else if (features.includes('sizeByPct')) {
          sizeParam = 'pct:' + formatPercentage(100 / scale);
        }
      } else {
        regionParam = 'full';
        if (supportsListedSizes) {
          sizeParam = sizes[zoom][0] + ',' + (version == Versions.VERSION3 ? sizes[zoom][1] : '');
        } else {
          sizeParam = version == Versions.VERSION3 ? 'max' : 'full';
        }
      }
      return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
    };

    const IiifTileClass = CustomTile.bind(null, tileGrid);

    super({
      attributions: options.attributions,
      attributionsCollapsible: options.attributionsCollapsible,
      cacheSize: options.cacheSize,
      crossOrigin: options.crossOrigin,
      opaque: options.opaque,
      projection: options.projection,
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      state: options.state,
      tileClass: IiifTileClass,
      transition: options.transition,
      wrapX: options.wrapX !== undefined ? options.wrapX : false,
      tileGrid: tileGrid,
      tilePixelRatio: options.tilePixelRatio,
      tileUrlFunction: tileUrlFunction
    });

  }

}

export default IIIF;
<commit_msg>Remove IIIF source rounding workarounds<commit_after>/**
 * @module ol/source/IIIF
 */

import {DEFAULT_TILE_SIZE} from '../tilegrid/common.js';
import {getTopLeft} from '../extent.js';
import {CustomTile} from './Zoomify.js';
import {Versions} from '../format/IIIFInfo.js';
import {assert} from '../asserts.js';
import TileGrid from '../tilegrid/TileGrid.js';
import TileImage from './TileImage.js';

/**
 * @typedef {Object} Options
 * @property {import("./Source.js").AttributionLike} [attributions] Attributions.
 * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.
 * @property {number} [cacheSize]
 * @property {null|string} [crossOrigin]
 * @property {import("../proj.js").ProjectionLike} [projection]
 * @property {number} [tilePixelRatio]
 * @property {number} [reprojectionErrorThreshold=0.5]
 * @property {string} [url] Base URL of the IIIF Image service.
 * This shoulf be the same as the IIIF Image @id.
 * @property {import("../size.js").Size} [size] Size of the image [width, height].
 * @property {import("../size.js").Size[]} [sizes] Supported scaled image sizes.
 * Content of the IIIF info.json 'sizes' property, but as array of Size objects.
 * @property {import("../extent.js").Extent} [extent=[0, -height, width, 0]]
 * @property {number} [transition]
 * @property {number|import("../size.js").Size} [tileSize] Tile size.
 * Same tile size is used for all zoom levels. If tile size is a number,
 * a square tile is assumed. If the IIIF image service supports arbitrary
 * tiling (sizeByH, sizeByW or sizeByPct as well as regionByPx and regionByPct
 * are supported), the default tilesize is 256.
 * @property {boolean} [wrapX=false]
 */

function formatPercentage(percentage) {
  return percentage.toLocaleString('en', {maximumFractionDigits: 10});
}

/**
 * @classdesc
 * Layer source for tile data in IIIF format.
 * @api
 */
class IIIF extends TileImage {

  constructor(opt_options) {

    const options = opt_options || {};

    let baseUrl = options.url || '';
    baseUrl = baseUrl + (baseUrl.lastIndexOf('/') === baseUrl.length - 1 || baseUrl === '' ? '' : '/');
    const version = options.version || Versions.VERSION2;
    const sizes = options.sizes || [];
    const size = options.size;
    assert(size != undefined && Array.isArray(size) && size.length == 2 &&
      !isNaN(size[0]) && size[0] > 0 && !isNaN(size[1] && size[1] > 0), 60);
    const width = size[0];
    const height = size[1];
    const tileSize = options.tileSize;
    const format = options.format || 'jpg';
    const quality = options.quality || (options.version == Versions.VERSION1 ? 'native' : 'default');
    let resolutions = options.resolutions || [];
    const features = options.features || [];
    const extent = options.extent || [0, -height, width, 0];

    const supportsListedSizes = sizes != undefined && Array.isArray(sizes) && sizes.length > 0;
    const supportsListedTiles = tileSize != undefined && (Number.isInteger(tileSize) && tileSize > 0 || Array.isArray(tileSize) && tileSize.length > 0);
    const supportsArbitraryTiling = features != undefined && Array.isArray(features) &&
      (features.includes('regionByPx') || features.includes('regionByPct')) &&
      (features.includes('sizeByWh') || features.includes('sizeByH') ||
      features.includes('sizeByW') || features.includes('sizeByPct'));

    let tileWidth,
        tileHeight,
        maxZoom;

    resolutions.sort(function(a, b) {
      return b - a;
    });

    if (supportsListedTiles || supportsArbitraryTiling) {
      if (tileSize != undefined) {
        if (Number.isInteger(tileSize) && tileSize > 0) {
          tileWidth = tileSize;
          tileHeight = tileSize;
        } else if (Array.isArray(tileSize) && tileSize.length > 0) {
          if (tileSize.length == 1 || tileSize[1] == undefined && Number.isInteger(tileSize[0])) {
            tileWidth = tileSize[0];
            tileHeight = tileSize[0];
          }
          if (tileSize.length == 2) {
            if (Number.isInteger(tileSize[0]) && Number.isInteger(tileSize[1])) {
              tileWidth = tileSize[0];
              tileHeight = tileSize[1];
            } else if (tileSize[0] == undefined && Number.isInteger(tileSize[1])) {
              tileWidth = tileSize[1];
              tileHeight = tileSize[1];
            }
          }
        }
      }
      if (tileWidth === undefined || tileHeight === undefined) {
        tileWidth = DEFAULT_TILE_SIZE;
        tileHeight = DEFAULT_TILE_SIZE;
      }
      if (resolutions.length == 0) {
        maxZoom = Math.max(
          Math.ceil(Math.log(width / tileWidth) / Math.LN2),
          Math.ceil(Math.log(height / tileHeight) / Math.LN2)
        );
        for (let i = maxZoom; i >= 0; i--) {
          resolutions.push(Math.pow(2, i));
        }
      } else {
        const maxScaleFactor = Math.max([...resolutions]);
        // TODO maxScaleFactor might not be a power to 2
        maxZoom = Math.round(Math.log(maxScaleFactor) / Math.LN2);
      }
    } else {
      // No tile support.
      tileWidth = width;
      tileHeight = height;
      resolutions = [];
      if (supportsListedSizes) {
        /*
         * 'sizes' provided. Use full region in different resolutions. Every
         * resolution has only one tile.
         */
        sizes.sort(function(a, b) {
          return a[0] - b[0];
        });
        for (let i = 0; i < sizes.length; i++) {
          const resolution = width / sizes[i][0];
          resolutions.push(resolution);
          maxZoom = i;
        }
      } else {
        // No useful image information at all. Try pseudo tile with full image.
        resolutions.push(1);
        sizes.push([width, height]);
        maxZoom = 0;
      }
    }

    const tileGrid = new TileGrid({
      tileSize: [tileWidth, tileHeight],
      extent: extent,
      origin: getTopLeft(extent),
      resolutions: resolutions
    });

    const tileUrlFunction = function(tileCoord, pixelRatio, projection) {
      let regionParam,
          sizeParam;
      const zoom = tileCoord[0];
      if (maxZoom < zoom) {
        return;
      }
      const tileX = tileCoord[1],
          tileY = tileCoord[2],
          scale = resolutions[zoom];
      if (tileX < 0 || Math.ceil(width / scale / tileWidth) <= tileX ||
      tileY < 0 || Math.ceil(height / scale / tileHeight) <= tileY) {
        return;
      }
      if (supportsArbitraryTiling || supportsListedTiles) {
        const regionX = tileX * tileWidth * scale,
            regionY = tileY * tileHeight * scale;
        let regionW = tileWidth * scale,
            regionH = tileHeight * scale,
            sizeW = tileWidth,
            sizeH = tileHeight;
        if (regionX + regionW > width) {
          regionW = width - regionX;
        }
        if (regionY + regionH > height) {
          regionH = height - regionY;
        }
        if (regionX + tileWidth * scale > width) {
          sizeW = Math.floor((width - regionX + scale - 1) / scale);
        }
        if (regionY + tileHeight * scale > height) {
          sizeH = Math.floor((height - regionY + scale - 1) / scale);
        }
        if (regionX == 0 && regionW == width && regionY == 0 && regionH == height) {
          // canonical full image region parameter is 'full', not 'x,y,w,h'
          regionParam = 'full';
        } else if (!supportsArbitraryTiling || features.includes('regionByPx')) {
          regionParam = regionX + ',' + regionY + ',' + regionW + ',' + regionH;
        } else if (features.includes('regionByPct')) {
          const pctX = formatPercentage(regionX / width * 100),
              pctY = formatPercentage(regionY / height * 100),
              pctW = formatPercentage(regionW / width * 100),
              pctH = formatPercentage(regionH / height * 100);
          regionParam = 'pct:' + pctX + ',' + pctY + ',' + pctW + ',' + pctH;
        }
        if (version == Versions.VERSION3 && (!supportsArbitraryTiling || features.includes('sizeByWh'))) {
          sizeParam = sizeW + ',' + sizeH;
        } else if (!supportsArbitraryTiling || features.includes('sizeByW')) {
          sizeParam = sizeW + ',';
        } else if (features.includes('sizeByH')) {
          sizeParam = ',' + sizeH;
        } else if (features.includes('sizeByWh')) {
          sizeParam = sizeW + ',' + sizeH;
        } else if (features.includes('sizeByPct')) {
          sizeParam = 'pct:' + formatPercentage(100 / scale);
        }
      } else {
        regionParam = 'full';
        if (supportsListedSizes) {
          sizeParam = sizes[zoom][0] + ',' + (version == Versions.VERSION3 ? sizes[zoom][1] : '');
        } else {
          sizeParam = version == Versions.VERSION3 ? 'max' : 'full';
        }
      }
      return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
    };

    const IiifTileClass = CustomTile.bind(null, tileGrid);

    super({
      attributions: options.attributions,
      attributionsCollapsible: options.attributionsCollapsible,
      cacheSize: options.cacheSize,
      crossOrigin: options.crossOrigin,
      opaque: options.opaque,
      projection: options.projection,
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      state: options.state,
      tileClass: IiifTileClass,
      transition: options.transition,
      wrapX: options.wrapX !== undefined ? options.wrapX : false,
      tileGrid: tileGrid,
      tilePixelRatio: options.tilePixelRatio,
      tileUrlFunction: tileUrlFunction
    });

  }

}

export default IIIF;
<|endoftext|>


<commit_before>var urlParser   = require('url');
var logger      = require('../util/logger');
var tasks       = require('./tasks');
var fork        = require('child_process').fork;

var seekInterval = ((process.env.RUN_INTERVAL || 5) * 1000); // 5 second default

process.on('uncaughtException',function(err){
    try
    {
        logger.logError('[RUNNER] uncaughtException: '+err.message);
    }
    catch (e)
    {
        console.error('[RUNNER] uncaughtException Exception '+e);
    }
});

function Runner()
{

    var me = this;
    var runTimer = setInterval(function(){
        me.startTasksToRun();
    }, seekInterval);

}

Runner.prototype.startTasksToRun = function()
{
    var me = this;
    tasks.getTasksToRun(function(err,data){
        if (!err)
        {
            var tasks = data.Items;
            for (var i = 0; i < tasks.length; i++)
            {
                me.startTask(tasks[i]);
            }
        }
        else
        {
            logger.logError('[RUNNER] startTasksToRun; '+err);
        }
    });

};

Runner.prototype.startTask = function(task)
{

    if (task)
    {

        try
        {

            tasks.setStatus(task.id, tasks.RUNNING, function(err, data) {

                if (err)
                {
                    logger.logError('[RUNNER] '+task.id+' Error occurred updating status before run; '+err,data);
                }

                var childProcess = fork('./runtask');
                childProcess.send( task );
                childProcess.on('message', function(data) {

                    // this will be logged
                    logger.logInfo('[RUNNER] '+task.id+' message received from child;',data);
                    if (data.result)
                    {
                        tasks.updateTask(task.id, data, function(err,data){
                            err && logger.logError('[RUNNER] '+task.id+' Error occurred updating task; '+err,data);
                        });
                    }

                });
                childProcess.on('error', function(err) {

                    logger.logError('[RUNNER] '+task.id+' child process error; '+err);
                    if (err)
                    {
                        tasks.updateTask(task.id, { error: err });
                    }

                });
                childProcess.on('close', function(code) {

                    if (code)
                    {
                        // might need to clean-up tasks if it didn't exit successfully
                        logger.logWarning('[RUNNER] '+task.id+' child process exited with code '+code);
                        tasks.setStatus(task.id, code, function(err,data){
                            if (err)
                            {
                                console.log("child runtask exit status set; FAILED; "+err, data);
                            }
                        });
                    }
                    else
                    {
                        tasks.setStatus(task.id, tasks.SUCCESS, function(err,data){
                            if (err)
                            {
                                console.log("child runtask exit status set; FAILED; "+err, data);
                            }
                            else
                            {
                                logger.logInfo('[RUNNER] '+task.id+' child process exited, all good');
                            }
                        });
                    }

                });
            });

        }
        catch (e)
        {
            console.error(e);
            tasks.updateTask(task.id, { error: e });
        }
    }
    else
    {
        logger.logError('[RUNNER] Start called with no task');
    }

};

module.exports = new Runner();<commit_msg>better fix for test and prod<commit_after>var urlParser   = require('url');
var path        = require('path');
var logger      = require('../util/logger');
var tasks       = require('./tasks');
var fork        = require('child_process').fork;

var seekInterval = ((process.env.RUN_INTERVAL || 5) * 1000); // 5 second default

process.on('uncaughtException',function(err){
    try
    {
        logger.logError('[RUNNER] uncaughtException: '+err.message);
    }
    catch (e)
    {
        console.error('[RUNNER] uncaughtException Exception '+e);
    }
});

function Runner()
{

    var me = this;
    var runTimer = setInterval(function(){
        me.startTasksToRun();
    }, seekInterval);

}

Runner.prototype.startTasksToRun = function()
{
    var me = this;
    tasks.getTasksToRun(function(err,data){
        if (!err)
        {
            var tasks = data.Items;
            for (var i = 0; i < tasks.length; i++)
            {
                me.startTask(tasks[i]);
            }
        }
        else
        {
            logger.logError('[RUNNER] startTasksToRun; '+err);
        }
    });

};

Runner.prototype.startTask = function(task)
{

    if (task)
    {

        try
        {

            tasks.setStatus(task.id, tasks.RUNNING, function(err, data) {

                if (err)
                {
                    logger.logError('[RUNNER] '+task.id+' Error occurred updating status before run; '+err,data);
                }

                var modulePath = __dirname+path.sep+'runtask';
                if (process.env.TEST_RUNNER) {
                    modulePath = './core/runtask';
                }
                var childProcess = fork(modulePath);
                childProcess.send( task );
                childProcess.on('message', function(data) {

                    // this will be logged
                    logger.logInfo('[RUNNER] '+task.id+' message received from child;',data);
                    if (data.result)
                    {
                        tasks.updateTask(task.id, data, function(err,data){
                            err && logger.logError('[RUNNER] '+task.id+' Error occurred updating task; '+err,data);
                        });
                    }

                });
                childProcess.on('error', function(err) {

                    logger.logError('[RUNNER] '+task.id+' child process error; '+err);
                    if (err)
                    {
                        tasks.updateTask(task.id, { error: err });
                    }

                });
                childProcess.on('close', function(code) {

                    if (code)
                    {
                        // might need to clean-up tasks if it didn't exit successfully
                        logger.logWarning('[RUNNER] '+task.id+' child process exited with code '+code);
                        tasks.setStatus(task.id, code, function(err,data){
                            if (err)
                            {
                                console.log("child runtask exit status set; FAILED; "+err, data);
                            }
                        });
                    }
                    else
                    {
                        tasks.setStatus(task.id, tasks.SUCCESS, function(err,data){
                            if (err)
                            {
                                console.log("child runtask exit status set; FAILED; "+err, data);
                            }
                            else
                            {
                                logger.logInfo('[RUNNER] '+task.id+' child process exited, all good');
                            }
                        });
                    }

                });
            });

        }
        catch (e)
        {
            console.error(e);
            tasks.updateTask(task.id, { error: e });
        }
    }
    else
    {
        logger.logError('[RUNNER] Start called with no task');
    }

};

module.exports = new Runner();<|endoftext|>


<commit_before>/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, o, undefined ){

	// o is overthrow reference from overthrow-polyfill.js
	if( o === undefined ){
		w.overthrow = o = {};
	}

	// Easing can use any of Robert Penner's equations (http://www.robertpenner.com/easing_terms_of_use.html). By default, overthrow includes ease-out-cubic
	// arguments: t = current iteration, b = initial value, c = end value, d = total iterations
	// use w.overthrow.easing to provide a custom function externally, or pass an easing function as a callback to the toss method
	o.easing = function (t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	};

	// requestAnimationFrame pfill
	var raf = (function(){
		return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			function( callback ){
				w.setTimeout(callback, 1000 / 60);
			};
	})();

	// tossing property is true during a programatic scroll
	o.tossing = false;

	// Keeper of intervals
	var timeKeeper;

	/* toss scrolls and element with easing

	// elem is the element to scroll
	// options hash:
		* left is the desired horizontal scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* top is the desired vertical scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* duration is the number of milliseconds the throw will take. Default is 100.
		* easing is an optional custom easing function. Default is w.overthrow.easing. Must follow the easing function signature

	*/
	o.toss = function( elem, options ){
		o.intercept();
		var i = 0,
			sLeft = elem.scrollLeft,
			sTop = elem.scrollTop,
			// Toss defaults
			op = {
				top: "+0",
				left: "+0",
				duration: 200,
				easing: o.easing,
				finished: function() {}
			},
			endLeft, endTop, finished = false;

		// Mixin based on predefined defaults
		if( options ){
			for( var j in op ){
				if( options[ j ] !== undefined ){
					op[ j ] = options[ j ];
				}
			}
		}

		// Convert relative values to ints
		// First the left val
		if( typeof op.left === "string" ){
			op.left = parseFloat( op.left );
			endLeft = op.left + sLeft;
		}
		else {
			endLeft = op.left;
			op.left = op.left - sLeft;
		}
		// Then the top val
		if( typeof op.top === "string" ){

			op.top = parseFloat( op.top );
			endTop = op.top + sTop;
		}
		else {
			endTop = op.top;
			op.top = op.top - sTop;
		}

		o.tossing = true;
		var startTime = new Date().getTime();
		var endTime = startTime + op.duration;
		var run = function(){
			var curTime = new Date().getTime();
			i = ( ( curTime - startTime ) / op.duration ) * op.duration;
			if( curTime < endTime ){
				elem.scrollLeft = op.easing( i, sLeft, op.left, op.duration );
				elem.scrollTop = op.easing( i, sTop, op.top, op.duration );
				if( o.tossing ){
					return raf( run );
				}
			}
			else{
				if( endLeft !== elem.scrollLeft ){
					elem.scrollLeft = endLeft;
				} else {
					// if the end of the vertical scrolling has taken place
					// we know that we're done here call the callback
					// otherwise signal that horizontal scrolling is complete
					if( finished ) {
						op.finished();
					}
					finished = true;
				}

				if( endTop !== elem.scrollTop ){
					elem.scrollTop = endTop;
				} else {
					// if the end of the horizontal scrolling has taken place
					// we know that we're done here call the callback
					if( finished ) {
						op.finished();
					}
					finished = true;
				}

				o.intercept();
			}
		};

		raf( run );

		// Return the values, post-mixin, with end values specified
		return { top: endTop, left: endLeft, duration: o.duration, easing: o.easing };
	};

	// Intercept any throw in progress
	o.intercept = function(){
		o.tossing = false;
	};

})( this, this.overthrow );
<commit_msg>fix overthrow complete event<commit_after>/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, o, undefined ){

	// o is overthrow reference from overthrow-polyfill.js
	if( o === undefined ){
		w.overthrow = o = {};
	}

	// Easing can use any of Robert Penner's equations (http://www.robertpenner.com/easing_terms_of_use.html). By default, overthrow includes ease-out-cubic
	// arguments: t = current iteration, b = initial value, c = end value, d = total iterations
	// use w.overthrow.easing to provide a custom function externally, or pass an easing function as a callback to the toss method
	o.easing = function (t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	};

	// requestAnimationFrame pfill
	var raf = (function(){
		return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			function( callback ){
				w.setTimeout(callback, 1000 / 60);
			};
	})();

	// tossing property is true during a programatic scroll
	o.tossing = false;

	// Keeper of intervals
	var timeKeeper;

	/* toss scrolls and element with easing

	// elem is the element to scroll
	// options hash:
		* left is the desired horizontal scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* top is the desired vertical scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* duration is the number of milliseconds the throw will take. Default is 100.
		* easing is an optional custom easing function. Default is w.overthrow.easing. Must follow the easing function signature

	*/
	o.toss = function( elem, options ){
		o.intercept();
		var i = 0,
			sLeft = elem.scrollLeft,
			sTop = elem.scrollTop,
			// Toss defaults
			op = {
				top: "+0",
				left: "+0",
				duration: 200,
				easing: o.easing,
				finished: function() {}
			},
			endLeft, endTop;

		// Mixin based on predefined defaults
		if( options ){
			for( var j in op ){
				if( options[ j ] !== undefined ){
					op[ j ] = options[ j ];
				}
			}
		}

		// Convert relative values to ints
		// First the left val
		if( typeof op.left === "string" ){
			op.left = parseFloat( op.left );
			endLeft = op.left + sLeft;
		}
		else {
			endLeft = op.left;
			op.left = op.left - sLeft;
		}
		// Then the top val
		if( typeof op.top === "string" ){

			op.top = parseFloat( op.top );
			endTop = op.top + sTop;
		}
		else {
			endTop = op.top;
			op.top = op.top - sTop;
		}

		o.tossing = true;
		var startTime = new Date().getTime();
		var endTime = startTime + op.duration;
		var run = function(){
			var curTime = new Date().getTime();
			i = ( ( curTime - startTime ) / op.duration ) * op.duration;
			if( curTime < endTime ){
				elem.scrollLeft = op.easing( i, sLeft, op.left, op.duration );
				elem.scrollTop = op.easing( i, sTop, op.top, op.duration );
				if( o.tossing ){
					return raf( run );
				}
			}
			else{
				elem.scrollLeft = endLeft;
				elem.scrollTop = endTop;
				if( op.finished ){
					op.finished();
				}
				o.intercept();
			}
		};

		raf( run );

		// Return the values, post-mixin, with end values specified
		return { top: endTop, left: endLeft, duration: o.duration, easing: o.easing };
	};

	// Intercept any throw in progress
	o.intercept = function(){
		o.tossing = false;
	};

})( this, this.overthrow );
<|endoftext|>


<commit_before>/**
 * A promisified version of the Hyperdrive API
 *
 * Note: The promises API does not currently include file descriptor operations.
*/

module.exports = class HyperdrivePromises {
  constructor (drive) {
    this.drive = drive
  }

  get key () {
    return this.drive.key
  }
  get discoveryKey () {
    return this.drive.discoveryKey
  }
  get version () {
    return this.drive.version
  }
  get metadata () {
    return this.drive.metadata
  }
  get writable () {
    return this.drive.metadata.writable
  }

  ready () {
    return new Promise((resolve, reject) => {
      this.drive.ready(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  close () {
    return new Promise((resolve, reject) => {
      this.drive.close(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  create (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.create(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })

  }

  createReadStream (name, opts) {
    return this.drive.createReadStream(name, opts)
  }

  readFile (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.readFile(name, opts, (err, contents) => {
        if (err) return reject(err)
        return resolve(contents)
      })
    })
  }

  createWriteStream (name, opts) {
    return this.drive.createWriteStream(name, opts)
  }

  writeFile (name, buf, opts) {
    return new Promise((resolve, reject) => {
      this.drive.writeFile(name, buf, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  createDiffStream (other, prefix, opts) {
    return this.drive.createDiffStream(other, prefix, opts)
  }

  createDirectoryStream (name, opts) {
    return this.drive.createDirectoryStream(name, opts)
  }

  replicate (isInitiator, opts) {
    return this.drive.replicate(isInitiator, opts)
  }

  truncate (name, size) {
    return new Promise((resolve, reject) => {
      this.drive.truncate(name, size, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  mkdir (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.mkdir(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })

  }

  lstat (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.lstat(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  stat (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.stat(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  access (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.access(name, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  exists (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.exists(name, opts, (exists) => {
        return resolve(exists)
      })
    })
  }

  readdir (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.readdir(name, opts, (err, entries) => {
        if (err) return reject(err)
        return resolve(entries)
      })
    })

  }

  unlink (name) {
    return new Promise((resolve, reject) => {
      this.drive.unlink(name, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  rmdir (name) {
    return new Promise((resolve, reject) => {
      this.drive.rmdir(name, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  checkout (version, opts) {
    return this.drive.checkout(version, opts).promises
  }

  destroyStorage () {
    return new Promise((resolve, reject) => {
      this.drive.destroyStorage(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  stats (path, opts) {
    return new Promise((resolve, reject) => {
      this.drive.stats(path, opts, (err, stats) => {
        if (err) return reject(err)
        return resolve(stats)
      })
    })
  }

  watchStats (path, opts) {
    return this.drive.watchStats(path, opts)
  }

  mirror () {
    return this.drive.mirror()
  }

  download (path, opts) {
    var handle = null
    const prom = new Promise((resolve, reject) => {
      handle = this.drive.download(path, opts, err => {
        if (err) return reject(err)
        return resolve(handle)
      })
    })
    prom.destroy = handle.destroy
    return prom
  }

  watch (name, onchange) {
    return this.drive.watch(name, onchange)
  }

  mount (path, key, opts) {
    return new Promise((resolve, reject) => {
      this.drive.mount(path, key, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  extension (name, message) {
    return this.drive.extension(name, message)
  }

  createMountStream (opts) {
    return this.drive.createMountStream(opts)
  }

  unmount (path) {
    return new Promise((resolve, reject) => {
      this.drive.unmount(path, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  symlink (target, linkname) {
    return new Promise((resolve, reject) => {
      this.drive.symlink(target, linkname, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  getAllMounts (opts) {
    return new Promise((resolve, reject) => {
      this.drive.getAllMounts(opts, (err, allMounts) => {
        if (err) return reject(err)
        return resolve(allMounts)
      })
    })
  }

  setMetadata (path, key, value) {
    return new Promise((resolve, reject) => {
      this.drive.setMetadata(path, key, value, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  removeMetadata (path, key) {
    return new Promise((resolve, reject) => {
      this.drive.removeMetadata(path, key, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  copy (from, to) {
    return new Promise((resolve, reject) => {
      this.drive.copy(from, to, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  createTag (name, version) {
    return new Promise((resolve, reject) => {
      this.drive.createTag(name, version, (err) => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  getAllTags () {
    return new Promise((resolve, reject) => {
      this.drive.getAllTags((err, allTags) => {
        if (err) return reject(err)
        return resolve(allTags)
      })
    })
  }

  deleteTag (name) {
    return new Promise((resolve, reject) => {
      this.drive.deleteTag(name, (err) => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  getTaggedVersion (name) {
    return new Promise((resolve, reject) => {
      this.drive.getTaggedVersion(name, (err, version) => {
        if (err) return reject(err)
        return resolve(version)
      })
    })
  }
}
<commit_msg>Add readlink to promises<commit_after>/**
 * A promisified version of the Hyperdrive API
 *
 * Note: The promises API does not currently include file descriptor operations.
*/

module.exports = class HyperdrivePromises {
  constructor (drive) {
    this.drive = drive
  }

  get key () {
    return this.drive.key
  }
  get discoveryKey () {
    return this.drive.discoveryKey
  }
  get version () {
    return this.drive.version
  }
  get metadata () {
    return this.drive.metadata
  }
  get writable () {
    return this.drive.metadata.writable
  }

  ready () {
    return new Promise((resolve, reject) => {
      this.drive.ready(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  close () {
    return new Promise((resolve, reject) => {
      this.drive.close(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  create (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.create(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })

  }

  createReadStream (name, opts) {
    return this.drive.createReadStream(name, opts)
  }

  readFile (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.readFile(name, opts, (err, contents) => {
        if (err) return reject(err)
        return resolve(contents)
      })
    })
  }

  createWriteStream (name, opts) {
    return this.drive.createWriteStream(name, opts)
  }

  writeFile (name, buf, opts) {
    return new Promise((resolve, reject) => {
      this.drive.writeFile(name, buf, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  createDiffStream (other, prefix, opts) {
    return this.drive.createDiffStream(other, prefix, opts)
  }

  createDirectoryStream (name, opts) {
    return this.drive.createDirectoryStream(name, opts)
  }

  replicate (isInitiator, opts) {
    return this.drive.replicate(isInitiator, opts)
  }

  truncate (name, size) {
    return new Promise((resolve, reject) => {
      this.drive.truncate(name, size, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  mkdir (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.mkdir(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })

  }

  lstat (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.lstat(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  stat (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.stat(name, opts, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  access (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.access(name, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  exists (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.exists(name, opts, (exists) => {
        return resolve(exists)
      })
    })
  }

  readdir (name, opts) {
    return new Promise((resolve, reject) => {
      this.drive.readdir(name, opts, (err, entries) => {
        if (err) return reject(err)
        return resolve(entries)
      })
    })

  }

  unlink (name) {
    return new Promise((resolve, reject) => {
      this.drive.unlink(name, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  rmdir (name) {
    return new Promise((resolve, reject) => {
      this.drive.rmdir(name, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  checkout (version, opts) {
    return this.drive.checkout(version, opts).promises
  }

  destroyStorage () {
    return new Promise((resolve, reject) => {
      this.drive.destroyStorage(err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  stats (path, opts) {
    return new Promise((resolve, reject) => {
      this.drive.stats(path, opts, (err, stats) => {
        if (err) return reject(err)
        return resolve(stats)
      })
    })
  }

  watchStats (path, opts) {
    return this.drive.watchStats(path, opts)
  }

  mirror () {
    return this.drive.mirror()
  }

  download (path, opts) {
    var handle = null
    const prom = new Promise((resolve, reject) => {
      handle = this.drive.download(path, opts, err => {
        if (err) return reject(err)
        return resolve(handle)
      })
    })
    prom.destroy = handle.destroy
    return prom
  }

  watch (name, onchange) {
    return this.drive.watch(name, onchange)
  }

  mount (path, key, opts) {
    return new Promise((resolve, reject) => {
      this.drive.mount(path, key, opts, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  extension (name, message) {
    return this.drive.extension(name, message)
  }

  createMountStream (opts) {
    return this.drive.createMountStream(opts)
  }

  unmount (path) {
    return new Promise((resolve, reject) => {
      this.drive.unmount(path, err => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  symlink (target, linkname) {
    return new Promise((resolve, reject) => {
      this.drive.symlink(target, linkname, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  readlink (name) {
    return new Promise((resolve, reject) => {
      this.drive.readlink(name, (err, linkname) => {
        if (err) return reject(err)
        return resolve(linkname)
      })
    })
  }

  getAllMounts (opts) {
    return new Promise((resolve, reject) => {
      this.drive.getAllMounts(opts, (err, allMounts) => {
        if (err) return reject(err)
        return resolve(allMounts)
      })
    })
  }

  setMetadata (path, key, value) {
    return new Promise((resolve, reject) => {
      this.drive.setMetadata(path, key, value, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  removeMetadata (path, key) {
    return new Promise((resolve, reject) => {
      this.drive.removeMetadata(path, key, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  copy (from, to) {
    return new Promise((resolve, reject) => {
      this.drive.copy(from, to, (err, st) => {
        if (err) return reject(err)
        return resolve(st)
      })
    })
  }

  createTag (name, version) {
    return new Promise((resolve, reject) => {
      this.drive.createTag(name, version, (err) => {
        if (err) return reject(err)
        return resolve(null)
      })
    })
  }

  getAllTags () {
    return new Promise((resolve, reject) => {
      this.drive.getAllTags((err, allTags) => {
        if (err) return reject(err)
        return resolve(allTags)
      })
    })
  }

  deleteTag (name) {
    return new Promise((resolve, reject) => {
      this.drive.deleteTag(name, (err) => {
        if (err) return reject(err)
        return resolve(null)
      })
    })

  }

  getTaggedVersion (name) {
    return new Promise((resolve, reject) => {
      this.drive.getTaggedVersion(name, (err, version) => {
        if (err) return reject(err)
        return resolve(version)
      })
    })
  }
}
<|endoftext|>


<commit_before>var decode = require("ent/decode")

const TYPES = {
  '1': 'onlineNumber',
  '4': 'comment'
}

function parseOnlineNumber(buf) {
  if (buf.length !== 6) {
    console.log("Can't easily handle number buffer: ", buf)
    return
  }

  return [{
    number: buf.readIntBE(2, 4)
  }]
}

const ignoreCommands = new Set(['PREPARING', 'LIVE'])

function parseComment(buf) {
  var pktLength = buf.readIntBE(2, 2)

  var actualBuf = buf.slice(4, pktLength)

  var payload = JSON.parse(actualBuf.toString("utf8"))

  var remainingBuf = buf.slice(pktLength)

  // TODO: parse this as well
  if (remainingBuf.length) {
    console.log("More message buf: %s", remainingBuf)
  }

  if (ignoreCommands.has(payload.cmd)) {
    return []
  }

  return [{
    nick: payload.info[2][1],
    message: decode(payload.info[1])
  }]
}

function parseUnknown(buf) {
  return [{
    buffer: buf
  }]
}

var parsers = {
  onlineNumber: parseOnlineNumber,
  comment: parseComment,
  unknown: parseUnknown
}

function parse(buf) {
  var typeFlag = buf.readIntBE(0, 2)

  var type = TYPES[typeFlag] || 'unknown'

  var messages = parsers[type](buf)

  messages.forEach(function(m) {
    if (!m.type) {
      m.type = type
    }
  })

  return messages
}

function composeJoinChannel(channelID) {
  var buf = new Buffer(12)
  buf.write("\x01\x01\x00\x0C", 0)
  buf.writeInt32BE(channelID, 4)
  buf.write("\x00\x00\x00\x00", 8)
  return buf
}

function composeHeartbeat() {
  return new Buffer("\x01\x02\x00\x04")
}

module.exports = {
  parse: parse,
  composeJoinChannel: composeJoinChannel,
  composeHeartbeat: composeHeartbeat,
}
<commit_msg>Always see int as uint in bytes, not bits<commit_after>var decode = require("ent/decode")

const TYPES = {
  '1': 'onlineNumber',
  '4': 'comment'
}

function parseOnlineNumber(buf) {
  if (buf.length !== 6) {
    console.log("Can't easily handle number buffer: ", buf)
    return
  }

  return [{
    number: buf.readUIntBE(2, 4)
  }]
}

const ignoreCommands = new Set(['PREPARING', 'LIVE'])

function parseComment(buf) {
  var pktLength = buf.readUIntBE(2, 2)

  var actualBuf = buf.slice(4, pktLength)

  var payload = JSON.parse(actualBuf.toString("utf8"))

  var remainingBuf = buf.slice(pktLength)

  // TODO: parse this as well
  if (remainingBuf.length) {
    console.log("More message buf: %s", remainingBuf)
  }

  if (ignoreCommands.has(payload.cmd)) {
    return []
  }

  return [{
    nick: payload.info[2][1],
    message: decode(payload.info[1])
  }]
}

function parseUnknown(buf) {
  return [{
    buffer: buf
  }]
}

var parsers = {
  onlineNumber: parseOnlineNumber,
  comment: parseComment,
  unknown: parseUnknown
}

function parse(buf) {
  var typeFlag = buf.readUIntBE(0, 2)

  var type = TYPES[typeFlag] || 'unknown'

  var messages = parsers[type](buf)

  messages.forEach(function(m) {
    if (!m.type) {
      m.type = type
    }
  })

  return messages
}

function composeJoinChannel(channelID) {
  var buf = new Buffer(12)
  buf.write("\x01\x01\x00\x0C", 0)
  buf.writeUIntBE(channelID, 4, 4)
  buf.write("\x00\x00\x00\x00", 8)
  return buf
}

function composeHeartbeat() {
  return new Buffer("\x01\x02\x00\x04")
}

module.exports = {
  parse: parse,
  composeJoinChannel: composeJoinChannel,
  composeHeartbeat: composeHeartbeat,
}
<|endoftext|>


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

  grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
    concat: {
      js: {
        options: {
          separator: grunt.util.linefeed + ';' + grunt.util.linefeed
        },
        files: {

          // vendor js //
          '../public/js/<%= pkg.name %>-vendor-<%= pkg.version %>.min.js':[
            'bower_components/angular/angular.min.js',
            'bower_components/angular-cookies/angular-cookies.min.js',
            'bower_components/angular-cookie/angular-cookie.min.js',
            'bower_components/ng-token-auth/dist/ng-token-auth.min.js',
            'bower_components/angular-ui-router/release/angular-ui-router.min.js',
            'bower_components/angular-bootstrap/ui-bootstrap.min.js',
            'bower_components/angular-loading-bar/build/loading-bar.min.js'
          ],

          // main application js //
          '../public/js/<%= pkg.name %>-app-<%= pkg.version %>.js': [
            'app/**/*.module.js',
            'app/app.js',
            'app/**/*.js',
            '!app/**/*.spec.js'
          ],

          // login application js //
          '../public/js/<%= pkg.name %>-login-<%= pkg.version %>.js': [
            'loginapp/login.js',
            'app/common/*.js',
            '!app/common/*.spec.js'
          ],
        }
      },
      css: {
        files:{
          '../public/css/<%= pkg.name %>-vendor-<%= pkg.version %>.css': [
            'bower_components/angular-material/angular-material.min.css',
            'bower_components/angular-material/themes/teal-theme.css',
            //'bower_components/bootstrap/dist/css/bootstrap.min.css',
            'bower_components/angular-loading-bar/build/loading-bar.min.css'
          ],
          '../public/css/<%= pkg.name %>-<%= pkg.version %>.css': [
            'app/**/*.css'
          ]
        }
      }
    },

    uglify: {
      options: {
        mangle: false,
        sourceMap: true
      },
      js: {
        files: {
          '../public/js/<%= pkg.name %>-app-<%= pkg.version %>.min.js': ['../public/js/<%= pkg.name %>-app-<%= pkg.version %>.js'],
          '../public/js/<%= pkg.name %>-login-<%= pkg.version %>.min.js': ['../public/js/<%= pkg.name %>-login-<%= pkg.version %>.js']
        }
      }
    },
    //less: {
    //  style: {
    //    files: {
    //      "public/css/style.css": "less/style.less"
    //    }
    //  }
    //},

    // Running unit tests
    // ------------------
    karma: {
      unit: {
        configFile: 'karma.conf.js',
        background: true
      }
    },

    // Running end to end tests
    // ------------------------
    //protractor: {
    //  options: {
    //    configFile: 'protractor.conf.js',
    //    keepAlive: true,  // false means stop the grunt process if test fails
    //    args: {}         // arguments passed to the protractor command
    //  },
    //  chrome: {
    //    options: {
    //      args: {
    //        browser: 'chrome'
    //      }
    //    }
    //  }
    //  // Adding the items below allows for running against multiple browsers with a single grunt protractor command
    //  //safari: {
    //  //  options:{
    //  //    args: {
    //  //      browser: 'safari'
    //  //    }
    //  //  }
    //  //},
    //  //firefox: {
    //  //  options:{
    //  //    args: {
    //  //      browser: 'firefox'
    //  //    }
    //  //  }
    //  //}
    //},
    ngtemplates: {
      'app': {
        src: 'app/**/*.html',
        dest: '../public/js/<%= pkg.name %>-templates-<%= pkg.version %>.js',
        options:{
          module: 'everycent',
          htmlmin:{
            collapseWhitespace:             true,
            removeAttributeQuotes:          true,
            removeComments:                 true, // Only if you don't use comment directives!
            removeEmptyAttributes:          true,
            removeRedundantAttributes:      true,
            removeScriptTypeAttributes:     true,
            removeStyleLinkTypeAttributes:  true
          }
        }
      }
    },
    watch: {
      js: {
        //files: ['javascript/*.js'],
        //tasks: ['concat:js', 'uglify:js'],
        files: ['app/*.js', 'app/**/*.js', 'loginapp/**/*.js'],
        tasks: ['concat:js', 'uglify:js'],
        options: {
          livereload: true,
        }
      },
      css: {
        //files: ['less/*.less'],
        files: ['app/**/*.css', 'loginapp/**/*.css'],
        tasks: ['concat:css'],
        options: {
          livereload: true,
        }
      },
      html: {
        //files: ['less/*.less'],
        //tasks: ['less:style'],
        files: ['../public/*.html', 'app/**/*.html', 'loginapp/**/*.html'],
        tasks:['ngtemplates'],
        options: {
          livereload: true
        }
      }
      //,
      //karma: {
      //  files: ['app/*.js', 'app/**/*.js'],
      //}
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  //grunt.loadNpmTasks('grunt-contrib-less');
  //grunt.loadNpmTasks('grunt-karma');
  //grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-angular-templates');

  grunt.registerTask('watching', [ 'watch' ]);
  //grunt.registerTask('concat', [ 'concat' ]);

  grunt.registerTask('default', ['watching']);
};
<commit_msg>Create new 'build' grunt task for rebuilding all libraries<commit_after>module.exports = function (grunt) {

  grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
    concat: {
      js: {
        options: {
          separator: grunt.util.linefeed + ';' + grunt.util.linefeed
        },
        files: {

          // vendor js //
          '../public/js/<%= pkg.name %>-vendor-<%= pkg.version %>.min.js':[
            'bower_components/angular/angular.min.js',
            'bower_components/angular-cookies/angular-cookies.min.js',
            'bower_components/angular-cookie/angular-cookie.min.js',
            'bower_components/ng-token-auth/dist/ng-token-auth.min.js',
            'bower_components/angular-ui-router/release/angular-ui-router.min.js',
            'bower_components/angular-bootstrap/ui-bootstrap.min.js',
            'bower_components/angular-loading-bar/build/loading-bar.min.js'
          ],

          // main application js //
          '../public/js/<%= pkg.name %>-app-<%= pkg.version %>.js': [
            'app/**/*.module.js',
            'app/app.js',
            'app/**/*.js',
            '!app/**/*.spec.js'
          ],

          // login application js //
          '../public/js/<%= pkg.name %>-login-<%= pkg.version %>.js': [
            'loginapp/login.js',
            'app/common/*.js',
            '!app/common/*.spec.js'
          ],
        }
      },
      css: {
        files:{
          '../public/css/<%= pkg.name %>-vendor-<%= pkg.version %>.css': [
            'bower_components/angular-material/angular-material.min.css',
            'bower_components/angular-material/themes/teal-theme.css',
            //'bower_components/bootstrap/dist/css/bootstrap.min.css',
            'bower_components/angular-loading-bar/build/loading-bar.min.css'
          ],
          '../public/css/<%= pkg.name %>-<%= pkg.version %>.css': [
            'app/**/*.css'
          ]
        }
      }
    },

    uglify: {
      options: {
        mangle: false,
        sourceMap: true
      },
      js: {
        files: {
          '../public/js/<%= pkg.name %>-app-<%= pkg.version %>.min.js': ['../public/js/<%= pkg.name %>-app-<%= pkg.version %>.js'],
          '../public/js/<%= pkg.name %>-login-<%= pkg.version %>.min.js': ['../public/js/<%= pkg.name %>-login-<%= pkg.version %>.js']
        }
      }
    },
    //less: {
    //  style: {
    //    files: {
    //      "public/css/style.css": "less/style.less"
    //    }
    //  }
    //},

    // Running unit tests
    // ------------------
    karma: {
      unit: {
        configFile: 'karma.conf.js',
        background: true
      }
    },

    // Running end to end tests
    // ------------------------
    //protractor: {
    //  options: {
    //    configFile: 'protractor.conf.js',
    //    keepAlive: true,  // false means stop the grunt process if test fails
    //    args: {}         // arguments passed to the protractor command
    //  },
    //  chrome: {
    //    options: {
    //      args: {
    //        browser: 'chrome'
    //      }
    //    }
    //  }
    //  // Adding the items below allows for running against multiple browsers with a single grunt protractor command
    //  //safari: {
    //  //  options:{
    //  //    args: {
    //  //      browser: 'safari'
    //  //    }
    //  //  }
    //  //},
    //  //firefox: {
    //  //  options:{
    //  //    args: {
    //  //      browser: 'firefox'
    //  //    }
    //  //  }
    //  //}
    //},
    ngtemplates: {
      'app': {
        src: 'app/**/*.html',
        dest: '../public/js/<%= pkg.name %>-templates-<%= pkg.version %>.js',
        options:{
          module: 'everycent',
          htmlmin:{
            collapseWhitespace:             true,
            removeAttributeQuotes:          true,
            removeComments:                 true, // Only if you don't use comment directives!
            removeEmptyAttributes:          true,
            removeRedundantAttributes:      true,
            removeScriptTypeAttributes:     true,
            removeStyleLinkTypeAttributes:  true
          }
        }
      }
    },
    watch: {
      js: {
        files: ['app/*.js', 'app/**/*.js', 'loginapp/**/*.js'],
        tasks: ['concat:js', 'uglify:js'],
        options: {
          livereload: true,
        }
      },
      css: {
        files: ['app/**/*.css', 'loginapp/**/*.css'],
        tasks: ['concat:css'],
        options: {
          livereload: true,
        }
      },
      html: {
        files: ['../public/*.html', 'app/**/*.html', 'loginapp/**/*.html'],
        tasks:['ngtemplates'],
        options: {
          livereload: true
        }
      }
      //,
      //karma: {
      //  files: ['app/*.js', 'app/**/*.js'],
      //}
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  //grunt.loadNpmTasks('grunt-contrib-less');
  //grunt.loadNpmTasks('grunt-karma');
  //grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-angular-templates');

  grunt.registerTask('watching', [ 'watch' ]);

  // Task for rebuilding all files
  grunt.registerTask('build', ['concat:js','uglify:js','ngtemplates','concat:css' ]);
  //grunt.registerTask('concat', [ 'concat' ]);

  grunt.registerTask('default', ['watching']);
};
<|endoftext|>


<commit_before>var decode = require("ent/decode")

function parseOnlineNumber(buf) {
  if (buf.length !== 6) {
    console.log("Can't easily handle number buffer: ", buf)
    return
  }

  return [{
    type: 'onlineNumber',
    number: buf.readUIntBE(2, 4)
  }]
}

var IGNORE_COMMANDS = new Set(['PREPARING', 'LIVE'])

function parseComment(buf) {
  var pktLength = buf.readUIntBE(2, 2)

  var actualBuf = buf.slice(4, pktLength)

  var payload = JSON.parse(actualBuf.toString("utf8"))

  var remainingBuf = buf.slice(pktLength)

  if (IGNORE_COMMANDS.has(payload.cmd)) {
    return []
  }

  return [{
    type: 'comment',
    nick: payload.info[2][1],
    message: decode(payload.info[1])
  }].concat(parse(remainingBuf))
}

function parseUnknown(buf) {
  return [{
    type: 'unknown',
    buffer: buf
  }]
}

var parsers = {
  '1': parseOnlineNumber,
  '4': parseComment,
}

// Circular recursion here. Just ignore warning from JSHint
// jshint -W003
function parse(buf) {
// jshint +W003
  if (!buf.length) {
    return []
  }

  var typeFlag = buf.readUIntBE(0, 2)

  return (parsers[typeFlag] || parseUnknown)(buf)
}

function composeJoinChannel(channelID) {
  var buf = new Buffer([
    1, 1, 0, 0xc,
    null, null, null, null,
    0, 0, 0, 0])
  buf.writeUIntBE(channelID, 4, 4)
  return buf
}

function composeHeartbeat() {
  return new Buffer([1, 2, 0, 4])
}

module.exports = {
  parse: parse,
  composeJoinChannel: composeJoinChannel,
  composeHeartbeat: composeHeartbeat,
}
<commit_msg>Keep parsing even if playload.cmd isn't supported<commit_after>var decode = require("ent/decode")

function parseOnlineNumber(buf) {
  if (buf.length !== 6) {
    console.log("Can't easily handle number buffer: ", buf)
    return
  }

  return [{
    type: 'onlineNumber',
    number: buf.readUIntBE(2, 4)
  }]
}

var IGNORE_COMMANDS = new Set(['PREPARING', 'LIVE'])

function parseComment(buf) {
  var pktLength = buf.readUIntBE(2, 2)

  var actualBuf = buf.slice(4, pktLength)

  var payload = JSON.parse(actualBuf.toString("utf8"))

  var remainingBuf = buf.slice(pktLength)

  if (IGNORE_COMMANDS.has(payload.cmd)) {
    return parse(remainingBuf)
  }

  return [{
    type: 'comment',
    nick: payload.info[2][1],
    message: decode(payload.info[1])
  }].concat(parse(remainingBuf))
}

function parseUnknown(buf) {
  return [{
    type: 'unknown',
    buffer: buf
  }]
}

var parsers = {
  '1': parseOnlineNumber,
  '4': parseComment,
}

// Circular recursion here. Just ignore warning from JSHint
// jshint -W003
function parse(buf) {
// jshint +W003
  if (!buf.length) {
    return []
  }

  var typeFlag = buf.readUIntBE(0, 2)

  return (parsers[typeFlag] || parseUnknown)(buf)
}

function composeJoinChannel(channelID) {
  var buf = new Buffer([
    1, 1, 0, 0xc,
    null, null, null, null,
    0, 0, 0, 0])
  buf.writeUIntBE(channelID, 4, 4)
  return buf
}

function composeHeartbeat() {
  return new Buffer([1, 2, 0, 4])
}

module.exports = {
  parse: parse,
  composeJoinChannel: composeJoinChannel,
  composeHeartbeat: composeHeartbeat,
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Robin Assistant
// @description Growth in peace
// @namespace   com.github.leoverto
// @include     https://www.reddit.com/robin/
// @include     https://www.reddit.com/robin
// @version     1.4
// @author      LeoVerto, Wiiplay123
// @grant       none
// ==/UserScript==

var autoVote = true;
var disableVoteMsgs = true;
var filterSpam = true;
var version = "1.4";

var ownName = $('.user a').text();
var spamCount = 0;
var voteCount = 0;
var userCount = 0;

var spamBlacklist = ["autovote", "staying", "group to stay", "pasta",
  "automatically voted", "stayers are betrayers", "stayers aint players",
  "mins remaining. status", ">>>>>>>>>>>>>>>>>>>>>>>",
  "<<<<<<<<<<<<<<<<<<<<<<", "growing is all we know", "f it ends on you",
  "timecube", "( ͡° ͜ʖ ͡°)"
];

function rewriteCSS() {
  $(".robin-chat--body").css({"height":"80vh"});
}

function sendMessage(msg) {
  $(".text-counter-input")[0].value = msg;
  $(".text-counter-input")[0].nextSibling.click();
}

// Custom options
function addOptions() {
  // Remove possible existing custom options
  $("#customOptions").remove();

  var customOptions = document.createElement("div");
  customOptions.id = "customOptions";
  customOptions.className = "robin-chat--sidebar-widget robin-chat--notification-widget";

  var header = "Robin-Assistant " + version + " Configuration"

  var autoVoteOption = createCheckbox("auto-vote",
    "Automatically vote Grow", autoVote, autoVoteListener, false);
  var voteMsgOption = createCheckbox("disable-vote-msgs",
    "Hide Vote Messages", disableVoteMsgs, disableVoteMsgsListener, true);
  var filterSpamOption = createCheckbox("filter-spam",
    "Filter common spam", filterSpam, filterSpamListener, true);

  $(customOptions).insertAfter("#robinDesktopNotifier");
  $(customOptions).append(header);
  $(customOptions).append(autoVoteOption);
  $(customOptions).append(voteMsgOption);
  $(customOptions).append(filterSpamOption);
}

function addInfo() {
  var userCount = "Users here: 0";

  $("#robinUserList").prepend(userCount);
}

function createCheckbox(name, description, checked, listener, counter) {
  var label = document.createElement("label");

  var checkbox = document.createElement("input");
  checkbox.name = name;
  checkbox.type = "checkbox";
  checkbox.onclick = listener;
  $(checkbox).prop("checked", checked);

  var description = document.createTextNode(description);

  label.appendChild(checkbox);
  label.appendChild(description);

  if (counter) {
    var counter = " Blocked: 0";
    $(label).append(counter);
  }

  return label;
}

// Listeners
function disableVoteMsgsListener(event) {
  if (event !== undefined) {
    disableVoteMsgs = $(event.target).is(":checked");
  }
}

function autoVoteListener(event) {
  if (event !== undefined) {
    autoVote = $(event.target).is(":checked");
  }
}

function filterSpamListener(event) {
  if (event !== undefined) {
    filterSpam = $(event.target).is(":checked");
  }
}

function updateCounter(id, value) {
  $("#" + id).text(value);
}

// Spam Filter
function checkSpam(message) {
  for (o = 0; o < spamBlacklist.length; o++) {
    if (message.toLowerCase().search(spamBlacklist[o]) != -1) {
      spamCount += 1;
      updateCounter("filter-spam-counter", spamCount);
      return true;
    }
  }
  return false;
}

// Generic updates
function update() {
  userCount = $("#robinUserList div").length;
  updateCounter("user-count", userCount);
}

// Mutation observer for new messages
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var added = mutation.addedNodes[0];

    // Filters all new messages
    if ($(added).hasClass("robin-message")) {
      var msg = added;
      var msgText = $(msg).find(".robin-message--message").text();
      //console.log(msgText)

      // Highlight messages starting with own user name
      if (msgText.startsWith(ownName)) {
        $(msg).css({background:'rgba(255, 0, 0, 0.3)', color: '#242424'});
      }

      // Filter vote messages
      if (disableVoteMsgs
        && $(msg).hasClass("robin--message-class--action")
        && msgText.startsWith("voted to ")) {
          $(msg).remove();
        }

      // Filter spam
      if (filterSpam) {
        if (checkSpam(msgText)) {
          $(msg).remove();
        }
      }
    }
  });
});
observer.observe($("#robinChatMessageList").get(0), {
  childList: true
});

// Main run
console.log("Robin-Assistant " + version + " enabled!");

rewriteCSS();
addOptions();
addInfo();
update();

// Auto-grow
setTimeout(function() {
  if (autoVote) {
    $(".robin--vote-class--increase")[0].click();
    console.log("WE SHALL GROW!");
  }
}, 10000);

// Update once a second
setInterval(function() {
  update();
}, 1000);
<commit_msg>Update robin-assistant.user.js<commit_after>// ==UserScript==
// @name        Robin Assistant
// @description Growth in peace
// @namespace   com.github.leoverto
// @include     https://www.reddit.com/robin/
// @include     https://www.reddit.com/robin
// @version     1.4
// @author      LeoVerto, Wiiplay123
// @grant       none
// ==/UserScript==

var autoVote = true;
var disableVoteMsgs = true;
var filterSpam = true;
var version = "1.4";

var ownName = $('.user a').text();
var spamCount = 0;
var voteCount = 0;
var userCount = 0;

var spamBlacklist = ["autovote", "staying", "group to stay", "pasta",
  "automatically voted", "stayers are betrayers", "stayers aint players",
  "mins remaining. status", ">>>>>>>>>>>>>>>>>>>>>>>",
  "TRUMPSBUTTPIRATES2016", "TRUMPSFIERYPOOPS2016", "ALL HAIL THE TACO BELL BOT",
  "<<<<<<<<<<<<<<<<<<<<<<", "growing is all we know", "f it ends on you",
  "timecube", "( ͡° ͜ʖ ͡°)"
];

function rewriteCSS() {
  $(".robin-chat--body").css({"height":"80vh"});
}

function sendMessage(msg) {
  $(".text-counter-input")[0].value = msg;
  $(".text-counter-input")[0].nextSibling.click();
}

// Custom options
function addOptions() {
  // Remove possible existing custom options
  $("#customOptions").remove();

  var customOptions = document.createElement("div");
  customOptions.id = "customOptions";
  customOptions.className = "robin-chat--sidebar-widget robin-chat--notification-widget";

  var header = "Robin-Assistant " + version + " Configuration"

  var autoVoteOption = createCheckbox("auto-vote",
    "Automatically vote Grow", autoVote, autoVoteListener, false);
  var voteMsgOption = createCheckbox("disable-vote-msgs",
    "Hide Vote Messages", disableVoteMsgs, disableVoteMsgsListener, true);
  var filterSpamOption = createCheckbox("filter-spam",
    "Filter common spam", filterSpam, filterSpamListener, true);

  $(customOptions).insertAfter("#robinDesktopNotifier");
  $(customOptions).append(header);
  $(customOptions).append(autoVoteOption);
  $(customOptions).append(voteMsgOption);
  $(customOptions).append(filterSpamOption);
}

function addInfo() {
  var userCount = "Users here: 0";

  $("#robinUserList").prepend(userCount);
}

function createCheckbox(name, description, checked, listener, counter) {
  var label = document.createElement("label");

  var checkbox = document.createElement("input");
  checkbox.name = name;
  checkbox.type = "checkbox";
  checkbox.onclick = listener;
  $(checkbox).prop("checked", checked);

  var description = document.createTextNode(description);

  label.appendChild(checkbox);
  label.appendChild(description);

  if (counter) {
    var counter = " Blocked: 0";
    $(label).append(counter);
  }

  return label;
}

// Listeners
function disableVoteMsgsListener(event) {
  if (event !== undefined) {
    disableVoteMsgs = $(event.target).is(":checked");
  }
}

function autoVoteListener(event) {
  if (event !== undefined) {
    autoVote = $(event.target).is(":checked");
  }
}

function filterSpamListener(event) {
  if (event !== undefined) {
    filterSpam = $(event.target).is(":checked");
  }
}

function updateCounter(id, value) {
  $("#" + id).text(value);
}

// Spam Filter
function checkSpam(message) {
  for (o = 0; o < spamBlacklist.length; o++) {
    if (message.toLowerCase().search(spamBlacklist[o]) != -1) {
      spamCount += 1;
      updateCounter("filter-spam-counter", spamCount);
      return true;
    }
  }
  return false;
}

// Generic updates
function update() {
  userCount = $("#robinUserList div").length;
  updateCounter("user-count", userCount);
}

// Mutation observer for new messages
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var added = mutation.addedNodes[0];

    // Filters all new messages
    if ($(added).hasClass("robin-message")) {
      var msg = added;
      var msgText = $(msg).find(".robin-message--message").text();
      //console.log(msgText)

      // Highlight messages starting with own user name
      if (msgText.startsWith(ownName)) {
        $(msg).css({background:'rgba(255, 0, 0, 0.3)', color: '#242424'});
      }

      // Filter vote messages
      if (disableVoteMsgs
        && $(msg).hasClass("robin--message-class--action")
        && msgText.startsWith("voted to ")) {
          $(msg).remove();
        }

      // Filter spam
      if (filterSpam) {
        if (checkSpam(msgText)) {
          $(msg).remove();
        }
      }
    }
  });
});
observer.observe($("#robinChatMessageList").get(0), {
  childList: true
});

// Main run
console.log("Robin-Assistant " + version + " enabled!");

rewriteCSS();
addOptions();
addInfo();
update();

// Auto-grow
setTimeout(function() {
  if (autoVote) {
    $(".robin--vote-class--increase")[0].click();
    console.log("WE SHALL GROW!");
  }
}, 10000);

// Update once a second
setInterval(function() {
  update();
}, 1000);
<|endoftext|>


<commit_before>const prefix = "/"
const version = require('../package.json').version;
const moment = require('moment-timezone');
module.exports = message => {
	var d = new Date();
	if (!message.content.startsWith(prefix)) return;
	if (message.author.bot) return;
	const client = message.client;
	let args = message.content.split(' ');
	const command = args.shift().slice(prefix.length);
	const guild = client.guilds.get("179445290795794432");

if (client.user.presence['status'] == 'dnd' && message.author.id !== '179443176279375872') return;

if (!command) {
	return;
}

function toTimeZone(d, zone) {
 var format = 'YYYY/MM/DD HH:mm:ss';
 return moment(d, format).tz(zone).format(format);
};

console.log(`
Command (${command}) Trigger. At: ${toTimeZone(d, "Asia/Hong_Kong")}
By: ${message.author.tag}, From: ${message.guild.name}`);

	try {
		guild.channels.find('name', 'aiw-log').send(`Command : ( ${command} ) Trigger \n${toTimeZone(d, "Asia/Hong_Kong")},\nBy: ${message.author.tag}`);
		let cmdFile = require(`../commands/${command}`);
		cmdFile.run(client, message, args);
	} catch (error) {
			console.log(`\n${error}`);
			message.channel.send('⚠Error : ' + error.message).then(response => response.delete(10000));
			 guild.channels.find('name', 'aiw-log').send({embed: {
			 	color: 10158080,
			 	description: '\`' + '------ 御坂網絡  ' + version + ' ------' + '\`\n' + 'Failed Execute Command : ' + command + `\nInput By : ` + message.author.tag + '\nAt : ' + toTimeZone(d, "Asia/Hong_Kong") + '\nFrom : ' + message.guild  + '\n\`\`\`js\n' + error.stack + '\`\`\`'
			 }});
		}

};
<commit_msg>Update message.js<commit_after>const prefix = "/"
const version = require('../package.json').version;
const moment = require('moment-timezone');
module.exports = message => {
	var d = new Date();
	if (!message.content.startsWith(prefix)) return;
	if (message.author.bot) return;
	const client = message.client;
	let args = message.content.split(' ');
	const command = args.shift().slice(prefix.length);
	const guild = client.guilds.get("179445290795794432");

if (client.user.presence['status'] == 'dnd' && message.author.id !== '179443176279375872') return;

if (!command) {
	return;
}

function toTimeZone(d, zone) {
 var format = 'YYYY/MM/DD HH:mm:ss';
 return moment(d, format).tz(zone).format(format);
};

console.log(`
Command (${command}) Trigger. At: ${toTimeZone(d, "Asia/Hong_Kong")}
By: ${message.author.tag}, From: ${message.guild.name}`);

	try {
		guild.channels.find('name', 'aiw-log').send(`Command : ( ${command} ) Trigger \n${toTimeZone(d, "Asia/Hong_Kong")},\nBy: ${message.author.tag}`);
		let cmdFile = require(`../commands/${command}`);
		cmdFile.run(client, message, args);
	} catch (error) {
			console.log(`\n${error}`);
			 guild.channels.find('name', 'aiw-log').send({embed: {
			 	color: 10158080,
			 	description: '\`' + '------ 御坂網絡  ' + version + ' ------' + '\`\n' + 'Failed Execute Command : ' + command + `\nInput By : ` + message.author.tag + '\nAt : ' + toTimeZone(d, "Asia/Hong_Kong") + '\nFrom : ' + message.guild  + '\n\`\`\`js\n' + error.stack + '\`\`\`'
			 }});
		}

};
<|endoftext|>


<commit_before>/* eslint-disable no-var */
var path = require('path')
var webpack = require('webpack')

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require('./package.json').version)
    })
  ],
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: [path.resolve(__dirname, './node_modules')]
        // config in .babelrc
      },
      {
        test: /\.scss$/,
        loaders: ['css', 'sass?includePaths[]='
            + require('node-bourbon').includePaths
            + '&includePaths[]='
            + path.resolve(__dirname, './src/base/scss')
        ],
        include: path.resolve(__dirname, 'src')
      },
      {
        test: /\.(png|woff|eot|ttf|swf|cur)/, loader: 'url-loader?limit=1'
      },
      {
        test: /\.svg/, loader: 'svg-inline'
      },
      {
        test: /\.html/, loader: 'html?minimize=false'
      }
    ]
  },
  resolve: {
    alias: { 'clappr-zepto': 'clappr-zepto/zepto.js' },
    root: path.resolve(__dirname, 'src'),
    extensions: ['', '.js']
  }
}
<commit_msg>fix(webpack): update config to support 2.4+<commit_after>/* eslint-disable no-var */
var path = require('path')
var webpack = require('webpack')

var DirectoryNamedWebpackPlugin = require('directory-named-webpack-plugin')

module.exports = {
  plugins: [
    new DirectoryNamedWebpackPlugin(true),
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require('./package.json').version)
    })
  ],
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: [path.resolve(__dirname, './node_modules')]
        // config in .babelrc
      },
      {
        test: /\.scss$/,
        loaders: ['css-loader', 'sass-loader?includePaths[]='
            + require('node-bourbon').includePaths
            + '&includePaths[]='
            + path.resolve(__dirname, './src/base/scss')
        ],
        include: path.resolve(__dirname, 'src')
      },
      {
        test: /\.(png|woff|eot|ttf|swf|cur)/, loader: 'url-loader?limit=1'
      },
      {
        test: /\.svg/, loader: 'svg-inline-loader'
      },
      {
        test: /\.html/, loader: 'html-loader?minimize=false'
      }
    ]
  },
  resolve: {
    alias: {
      'clappr-zepto': 'clappr-zepto/zepto.js'
    },
    modules: [path.resolve(__dirname, 'src'), 'node_modules']
  }
}
<|endoftext|>


<commit_before>
var sys = require('sys');

var dom = require('../../lib/jsdom/level1/core').dom.level1.core;
var browser = require('../../lib/jsdom/browser/index').windowAugmentation(dom);

var document = browser.document;
var window = browser.window;
var self = browser.self;
var navigator = browser.navigator;
var location = browser.location;

document.title = 'Test Title';

//GLOBAL
var el = document.createElement('div');
el.id = 'foo';
el.innerHTML = 'This is a test This is another test ';
document.body.appendChild(el);

//SCOPED
var el2 = browser.document.createElement('div');
el2.id = 'foo2bar';
el2.innerHTML = 'This is a test This is another test ';
browser.document.body.appendChild(el2);

sys.puts('getElementByid(foo2bar): ' + browser.document.getElementById('foo2bar'));
sys.puts('getElementByid(foo): ' + browser.document.getElementById('foo'));
sys.puts('getElementByTagName(em): ' + browser.document.getElementsByTagName('em'));
sys.puts('getElementByClassName(odd): ' + browser.document.getElementsByClassName('odd'));

sys.puts('');
sys.puts('document.body.outerHTML: ');
sys.puts(document.body.outerHTML);

sys.puts('document.outerHTML: ');
sys.puts(document.outerHTML);
<commit_msg>The browser example requires level2/html as it uses document.body<commit_after>
var sys = require('sys');

var dom = require('../../lib/jsdom/level2/html').dom.level2.html;
var browser = require('../../lib/jsdom/browser/index').windowAugmentation(dom);

var document = browser.document;
var window = browser.window;
var self = browser.self;
var navigator = browser.navigator;
var location = browser.location;

document.title = 'Test Title';

//GLOBAL
var el = document.createElement('div');
el.id = 'foo';
el.innerHTML = 'This is a test This is another test ';
document.body.appendChild(el);

//SCOPED
var el2 = browser.document.createElement('div');
el2.id = 'foo2bar';
el2.innerHTML = 'This is a test This is another test ';
browser.document.body.appendChild(el2);

sys.puts('getElementByid(foo2bar): ' + browser.document.getElementById('foo2bar'));
sys.puts('getElementByid(foo): ' + browser.document.getElementById('foo'));
sys.puts('getElementByTagName(em): ' + browser.document.getElementsByTagName('em'));
sys.puts('getElementByClassName(odd): ' + browser.document.getElementsByClassName('odd'));

sys.puts('');
sys.puts('document.body.outerHTML: ');
sys.puts(document.body.outerHTML);

sys.puts('document.outerHTML: ');
sys.puts(document.outerHTML);
<|endoftext|>