<commit_before>goog.provide('ol.renderer.canvas.VectorLayer');

goog.require('goog.vec.Mat4');
goog.require('ol.Extent');
goog.require('ol.Size');
goog.require('ol.TileCache');
goog.require('ol.TileCoord');
goog.require('ol.ViewHint');
goog.require('ol.filter.Extent');
goog.require('ol.filter.Geometry');
goog.require('ol.filter.Logical');
goog.require('ol.filter.LogicalOperator');
goog.require('ol.geom.GeometryType');
goog.require('ol.layer.Vector');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.canvas.Renderer');
goog.require('ol.style.LiteralLine');
goog.require('ol.style.LiteralPolygon');
goog.require('ol.style.LiteralShape');
goog.require('ol.style.ShapeType');

/**
 * @constructor
 * @extends {ol.renderer.canvas.Layer}
 * @param {ol.renderer.Map} mapRenderer Map renderer.
 * @param {ol.layer.Vector} layer Vector layer.
 */
ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {

  goog.base(this, mapRenderer, layer);

  /**
   * Final canvas made available to the map renderer.
   * @private
   * @type {HTMLCanvasElement}
   */
  this.canvas_ = /** @type {HTMLCanvasElement} */
      (goog.dom.createElement(goog.dom.TagName.CANVAS));

  /**
   * @private
   * @type {CanvasRenderingContext2D}
   */
  this.context_ =  /** @type {CanvasRenderingContext2D} */
      this.canvas_.getContext('2d');

  /**
   * @private
   * @type {!goog.vec.Mat4.Number}
   */
  this.transform_ = goog.vec.Mat4.createNumber();

  /**
   * Interim canvas for drawing newly visible features.
   * @private
   * @type {HTMLCanvasElement}
   */
  this.sketchCanvas_ = /** @type {HTMLCanvasElement} */
      (goog.dom.createElement(goog.dom.TagName.CANVAS));

  /**
   * @private
   * @type {!goog.vec.Mat4.Number}
   */
  this.sketchTransform_ = goog.vec.Mat4.createNumber();

  /**
   * @private
   * @type {ol.TileCache}
   */
  this.tileCache_ = new ol.TileCache(
      ol.renderer.canvas.VectorLayer.TILECACHE_SIZE);

  /**
   * @private
   * @type {HTMLCanvasElement}
   */
  this.tileArchetype_ = null;

  /**
   * Geometry filters in rendering order.
   * @private
   * @type {Array.<ol.filter.Geometry>}
   * TODO: deal with multis
   */
  this.geometryFilters_ = [
    new ol.filter.Geometry(ol.geom.GeometryType.POLYGON),
    new ol.filter.Geometry(ol.geom.GeometryType.LINESTRING),
    new ol.filter.Geometry(ol.geom.GeometryType.POINT)
  ];

  /**
   * @private
   * @type {number}
   */
  this.renderedResolution_;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.renderedExtent_ = null;

  /**
   * Flag to be set internally when we know something has changed that suggests
   * we need to re-render.
   * TODO: discuss setting this for all layers when something changes before
   * calling map.render().
   * @private
   * @type {boolean}
   */
  this.dirty_ = false;

  // TODO: implement layer.setStyle(style) where style is a set of rules
  // and a rule has a filter and array of symbolizers
  var symbolizers = {};
  symbolizers[ol.geom.GeometryType.POINT] = new ol.style.LiteralShape({
    type: ol.style.ShapeType.CIRCLE,
    size: 10,
    fillStyle: '#ffcc99',
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 0.75
  });
  symbolizers[ol.geom.GeometryType.LINESTRING] = new ol.style.LiteralLine({
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 1
  });
  symbolizers[ol.geom.GeometryType.POLYGON] = new ol.style.LiteralPolygon({
    fillStyle: '#ffcc99',
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 0.5
  });
  // TODO: remove this
  this.symbolizers_ = symbolizers;

  /**
   * @private
   * @type {boolean}
   */
  this.pendingCachePrune_ = false;

  /**
   * Grid used for internal generation of canvas tiles.  This is created
   * lazily so we have access to the view projection.
   *
   * @private
   * @type {ol.TileGrid}
   */
  this.tileGrid_ = null;

};
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.getImage = function() {
  return this.canvas_;
};

/**
 * @return {ol.layer.Vector} Vector layer.
 */
ol.renderer.canvas.VectorLayer.prototype.getVectorLayer = function() {
  return /** @type {ol.layer.Vector} */ (this.getLayer());
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.getTransform = function() {
  return this.transform_;
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.renderFrame =
    function(frameState, layerState) {

  // TODO: consider bailing out here if rendered center and resolution
  // have not changed.  Requires that other change listeners set a dirty flag.

  var view2DState = frameState.view2DState,
      resolution = view2DState.resolution,
      extent = frameState.extent,
      source = this.getVectorLayer().getVectorSource(),
      tileGrid = this.tileGrid_;

  if (goog.isNull(tileGrid)) {
    // lazy tile source creation to match the view projection
    tileGrid = ol.tilegrid.createForProjection(
        view2DState.projection,
        22, // should be no harm in going big here - ideally, it would be ∞
        new ol.Size(512, 512));
    this.tileGrid_ = tileGrid;
  }

  // set up transform for the layer canvas to be drawn to the map canvas
  var tileSize = tileGrid.getTileSize(),
      z = tileGrid.getZForResolution(resolution),
      tileResolution = tileGrid.getResolution(z),
      tileRange = tileGrid.getTileRangeForExtentAndResolution(
          extent, tileResolution),
      tileRangeExtent = tileGrid.getTileRangeExtent(z, tileRange),
      sketchOrigin = tileRangeExtent.getTopLeft(),
      transform = this.transform_;

  goog.vec.Mat4.makeIdentity(transform);
  goog.vec.Mat4.translate(transform,
      frameState.size.width / 2,
      frameState.size.height / 2,
      0);
  goog.vec.Mat4.scale(transform,
      tileResolution / resolution, tileResolution / resolution, 1);
  goog.vec.Mat4.rotateZ(transform, view2DState.rotation);
  goog.vec.Mat4.translate(transform,
      (sketchOrigin.x - view2DState.center.x) / tileResolution,
      (view2DState.center.y - sketchOrigin.y) / tileResolution,
      0);

  /**
   * Fastest path out of here.  This method is called many many times while
   * there is nothing to do (e.g. while waiting for tiles from every other
   * layer to load.)  Do not put anything above here that is more expensive than
   * necessary.  And look for ways to get here faster.
   */
  if (!this.dirty_ && this.renderedResolution_ === tileResolution &&
      // TODO: extent.equals()
      this.renderedExtent_.toString() === tileRangeExtent.toString()) {
    return;
  }

  if (goog.isNull(this.tileArchetype_)) {
    this.tileArchetype_ = /** @type {HTMLCanvasElement} */
        goog.dom.createElement(goog.dom.TagName.CANVAS);
    this.tileArchetype_.width = tileSize.width;
    this.tileArchetype_.height = tileSize.height;
  }

  /**
   * Prepare the sketch canvas.  This covers the currently visible tile range
   * and will have rendered all newly visible features.
   */
  var sketchCanvas = this.sketchCanvas_;
  var sketchSize = new ol.Size(
      tileSize.width * tileRange.getWidth(),
      tileSize.height * tileRange.getHeight());

  // transform for map coords to sketch canvas pixel coords
  var sketchTransform = this.sketchTransform_;
  var halfWidth = sketchSize.width / 2;
  var halfHeight = sketchSize.height / 2;
  goog.vec.Mat4.makeIdentity(sketchTransform);
  goog.vec.Mat4.translate(sketchTransform,
      halfWidth,
      halfHeight,
      0);
  goog.vec.Mat4.scale(sketchTransform,
      1 / tileResolution,
      -1 / tileResolution,
      1);
  goog.vec.Mat4.translate(sketchTransform,
      -(sketchOrigin.x + halfWidth * tileResolution),
      -(sketchOrigin.y - halfHeight * tileResolution),
      0);

  // clear/resize sketch canvas
  sketchCanvas.width = sketchSize.width;
  sketchCanvas.height = sketchSize.height;

  var sketchCanvasRenderer = new ol.renderer.canvas.Renderer(
      sketchCanvas, sketchTransform);

  // clear/resize final canvas
  var finalCanvas = this.canvas_;
  finalCanvas.width = sketchSize.width;
  finalCanvas.height = sketchSize.height;
  var finalContext = this.context_;

  var renderedFeatures = {};
  var tilesToRender = {};
  var tile, tileCoord, key, tileState, x, y;
  // render features by geometry type
  var filters = this.geometryFilters_,
      numFilters = filters.length,
      i, spatialFilter, extentFilter, type, features, symbolizer;
  for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
    for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
      tileCoord = new ol.TileCoord(z, x, y);
      key = tileCoord.toString();
      if (this.tileCache_.containsKey(key)) {
        tilesToRender[key] = tileCoord;
      } else if (!frameState.viewHints[ol.ViewHint.ANIMATING]) {
        tilesToRender[key] = tileCoord;
        extentFilter = new ol.filter.Extent(
            tileGrid.getTileCoordExtent(tileCoord));
        for (i = 0; i < numFilters; ++i) {
          spatialFilter = filters[i];
          type = spatialFilter.getType();
          features = source.getFeatures(new ol.filter.Logical(
              [spatialFilter, extentFilter], ol.filter.LogicalOperator.AND));
          if (features.length) {
            // TODO: layer.getSymbolizerLiterals(features) or similar
            symbolizer = this.symbolizers_[type];
            sketchCanvasRenderer.renderFeaturesByGeometryType(
                type, features, symbolizer);
          }
        }
      }
    }
  }

  this.dirty_ = true;
  for (key in tilesToRender) {
    tileCoord = tilesToRender[key];
    if (this.tileCache_.containsKey(key)) {
      tile = /** @type {HTMLCanvasElement} */ (this.tileCache_.get(key));
    } else {
      tile = /** @type {HTMLCanvasElement} */
          this.tileArchetype_.cloneNode(false);
      tile.getContext('2d').drawImage(sketchCanvas,
          (tileRange.minX - tileCoord.x) * tileSize.width,
          (tileCoord.y - tileRange.maxY) * tileSize.height);
      this.tileCache_.set(key, tile);
    }
    finalContext.drawImage(tile,
        tileSize.width * (tileCoord.x - tileRange.minX),
        tileSize.height * (tileRange.maxY - tileCoord.y));
    this.dirty_ = false;
  }

  this.renderedResolution_ = tileResolution;
  this.renderedExtent_ = tileRangeExtent;
  if (!this.pendingCachePrune_) {
    this.pendingCachePrune_ = true;
    frameState.postRenderFunctions.push(goog.bind(this.pruneTileCache_, this));
  }

};

/**
 * Get rid of tiles that exceed the cache capacity.
 * TODO: add a method to the cache to handle this
 * @private
 */
ol.renderer.canvas.VectorLayer.prototype.pruneTileCache_ = function() {
  while (this.tileCache_.canExpireCache()) {
    this.tileCache_.pop();
  }
  this.pendingCachePrune_ = false;
};

/**
 * @type {number}
 */
ol.renderer.canvas.VectorLayer.TILECACHE_SIZE = 128;
<commit_msg>Lint and names<commit_after>goog.provide('ol.renderer.canvas.VectorLayer');

goog.require('goog.vec.Mat4');
goog.require('ol.Extent');
goog.require('ol.Size');
goog.require('ol.TileCache');
goog.require('ol.TileCoord');
goog.require('ol.ViewHint');
goog.require('ol.filter.Extent');
goog.require('ol.filter.Geometry');
goog.require('ol.filter.Logical');
goog.require('ol.filter.LogicalOperator');
goog.require('ol.geom.GeometryType');
goog.require('ol.layer.Vector');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.canvas.Renderer');
goog.require('ol.style.LiteralLine');
goog.require('ol.style.LiteralPolygon');
goog.require('ol.style.LiteralShape');
goog.require('ol.style.ShapeType');
goog.require('ol.tilegrid.TileGrid');

/**
 * @constructor
 * @extends {ol.renderer.canvas.Layer}
 * @param {ol.renderer.Map} mapRenderer Map renderer.
 * @param {ol.layer.Vector} layer Vector layer.
 */
ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {

  goog.base(this, mapRenderer, layer);

  /**
   * Final canvas made available to the map renderer.
   * @private
   * @type {HTMLCanvasElement}
   */
  this.canvas_ = /** @type {HTMLCanvasElement} */
      (goog.dom.createElement(goog.dom.TagName.CANVAS));

  /**
   * @private
   * @type {CanvasRenderingContext2D}
   */
  this.context_ =  /** @type {CanvasRenderingContext2D} */
      this.canvas_.getContext('2d');

  /**
   * @private
   * @type {!goog.vec.Mat4.Number}
   */
  this.transform_ = goog.vec.Mat4.createNumber();

  /**
   * Interim canvas for drawing newly visible features.
   * @private
   * @type {HTMLCanvasElement}
   */
  this.sketchCanvas_ = /** @type {HTMLCanvasElement} */
      (goog.dom.createElement(goog.dom.TagName.CANVAS));

  /**
   * @private
   * @type {!goog.vec.Mat4.Number}
   */
  this.sketchTransform_ = goog.vec.Mat4.createNumber();

  /**
   * @private
   * @type {ol.TileCache}
   */
  this.tileCache_ = new ol.TileCache(
      ol.renderer.canvas.VectorLayer.TILECACHE_SIZE);

  /**
   * @private
   * @type {HTMLCanvasElement}
   */
  this.tileArchetype_ = null;

  /**
   * Geometry filters in rendering order.
   * @private
   * @type {Array.<ol.filter.Geometry>}
   * TODO: deal with multis
   */
  this.geometryFilters_ = [
    new ol.filter.Geometry(ol.geom.GeometryType.POLYGON),
    new ol.filter.Geometry(ol.geom.GeometryType.LINESTRING),
    new ol.filter.Geometry(ol.geom.GeometryType.POINT)
  ];

  /**
   * @private
   * @type {number}
   */
  this.renderedResolution_;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.renderedExtent_ = null;

  /**
   * Flag to be set internally when we know something has changed that suggests
   * we need to re-render.
   * TODO: discuss setting this for all layers when something changes before
   * calling map.render().
   * @private
   * @type {boolean}
   */
  this.dirty_ = false;

  // TODO: implement layer.setStyle(style) where style is a set of rules
  // and a rule has a filter and array of symbolizers
  var symbolizers = {};
  symbolizers[ol.geom.GeometryType.POINT] = new ol.style.LiteralShape({
    type: ol.style.ShapeType.CIRCLE,
    size: 10,
    fillStyle: '#ffcc99',
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 0.75
  });
  symbolizers[ol.geom.GeometryType.LINESTRING] = new ol.style.LiteralLine({
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 1
  });
  symbolizers[ol.geom.GeometryType.POLYGON] = new ol.style.LiteralPolygon({
    fillStyle: '#ffcc99',
    strokeStyle: '#ff9933',
    strokeWidth: 2,
    opacity: 0.5
  });
  // TODO: remove this
  this.symbolizers_ = symbolizers;

  /**
   * @private
   * @type {boolean}
   */
  this.pendingCachePrune_ = false;

  /**
   * Grid used for internal generation of canvas tiles.  This is created
   * lazily so we have access to the view projection.
   *
   * @private
   * @type {ol.tilegrid.TileGrid}
   */
  this.tileGrid_ = null;

};
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.getImage = function() {
  return this.canvas_;
};

/**
 * @return {ol.layer.Vector} Vector layer.
 */
ol.renderer.canvas.VectorLayer.prototype.getVectorLayer = function() {
  return /** @type {ol.layer.Vector} */ (this.getLayer());
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.getTransform = function() {
  return this.transform_;
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.renderFrame =
    function(frameState, layerState) {

  // TODO: consider bailing out here if rendered center and resolution
  // have not changed.  Requires that other change listeners set a dirty flag.

  var view2DState = frameState.view2DState,
      resolution = view2DState.resolution,
      extent = frameState.extent,
      source = this.getVectorLayer().getVectorSource(),
      tileGrid = this.tileGrid_;

  if (goog.isNull(tileGrid)) {
    // lazy tile source creation to match the view projection
    tileGrid = ol.tilegrid.createForProjection(
        view2DState.projection,
        22, // should be no harm in going big here - ideally, it would be ∞
        new ol.Size(512, 512));
    this.tileGrid_ = tileGrid;
  }

  // set up transform for the layer canvas to be drawn to the map canvas
  var tileSize = tileGrid.getTileSize(),
      z = tileGrid.getZForResolution(resolution),
      tileResolution = tileGrid.getResolution(z),
      tileRange = tileGrid.getTileRangeForExtentAndResolution(
          extent, tileResolution),
      tileRangeExtent = tileGrid.getTileRangeExtent(z, tileRange),
      sketchOrigin = tileRangeExtent.getTopLeft(),
      transform = this.transform_;

  goog.vec.Mat4.makeIdentity(transform);
  goog.vec.Mat4.translate(transform,
      frameState.size.width / 2,
      frameState.size.height / 2,
      0);
  goog.vec.Mat4.scale(transform,
      tileResolution / resolution, tileResolution / resolution, 1);
  goog.vec.Mat4.rotateZ(transform, view2DState.rotation);
  goog.vec.Mat4.translate(transform,
      (sketchOrigin.x - view2DState.center.x) / tileResolution,
      (view2DState.center.y - sketchOrigin.y) / tileResolution,
      0);

  /**
   * Fastest path out of here.  This method is called many many times while
   * there is nothing to do (e.g. while waiting for tiles from every other
   * layer to load.)  Do not put anything above here that is more expensive than
   * necessary.  And look for ways to get here faster.
   */
  if (!this.dirty_ && this.renderedResolution_ === tileResolution &&
      // TODO: extent.equals()
      this.renderedExtent_.toString() === tileRangeExtent.toString()) {
    return;
  }

  if (goog.isNull(this.tileArchetype_)) {
    this.tileArchetype_ = /** @type {HTMLCanvasElement} */
        goog.dom.createElement(goog.dom.TagName.CANVAS);
    this.tileArchetype_.width = tileSize.width;
    this.tileArchetype_.height = tileSize.height;
  }

  /**
   * Prepare the sketch canvas.  This covers the currently visible tile range
   * and will have rendered all newly visible features.
   */
  var sketchCanvas = this.sketchCanvas_;
  var sketchSize = new ol.Size(
      tileSize.width * tileRange.getWidth(),
      tileSize.height * tileRange.getHeight());

  // transform for map coords to sketch canvas pixel coords
  var sketchTransform = this.sketchTransform_;
  var halfWidth = sketchSize.width / 2;
  var halfHeight = sketchSize.height / 2;
  goog.vec.Mat4.makeIdentity(sketchTransform);
  goog.vec.Mat4.translate(sketchTransform,
      halfWidth,
      halfHeight,
      0);
  goog.vec.Mat4.scale(sketchTransform,
      1 / tileResolution,
      -1 / tileResolution,
      1);
  goog.vec.Mat4.translate(sketchTransform,
      -(sketchOrigin.x + halfWidth * tileResolution),
      -(sketchOrigin.y - halfHeight * tileResolution),
      0);

  // clear/resize sketch canvas
  sketchCanvas.width = sketchSize.width;
  sketchCanvas.height = sketchSize.height;

  var sketchCanvasRenderer = new ol.renderer.canvas.Renderer(
      sketchCanvas, sketchTransform);

  // clear/resize final canvas
  var finalCanvas = this.canvas_;
  finalCanvas.width = sketchSize.width;
  finalCanvas.height = sketchSize.height;
  var finalContext = this.context_;

  var renderedFeatures = {};
  var tilesToRender = {};
  var tile, tileCoord, key, tileState, x, y;
  // render features by geometry type
  var filters = this.geometryFilters_,
      numFilters = filters.length,
      i, geomFilter, extentFilter, type, features, symbolizer;
  for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
    for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
      tileCoord = new ol.TileCoord(z, x, y);
      key = tileCoord.toString();
      if (this.tileCache_.containsKey(key)) {
        tilesToRender[key] = tileCoord;
      } else if (!frameState.viewHints[ol.ViewHint.ANIMATING]) {
        tilesToRender[key] = tileCoord;
        extentFilter = new ol.filter.Extent(
            tileGrid.getTileCoordExtent(tileCoord));
        for (i = 0; i < numFilters; ++i) {
          geomFilter = filters[i];
          type = geomFilter.getType();
          features = source.getFeatures(new ol.filter.Logical(
              [geomFilter, extentFilter], ol.filter.LogicalOperator.AND));
          if (features.length) {
            // TODO: layer.getSymbolizerLiterals(features) or similar
            symbolizer = this.symbolizers_[type];
            sketchCanvasRenderer.renderFeaturesByGeometryType(
                type, features, symbolizer);
          }
        }
      }
    }
  }

  this.dirty_ = true;
  for (key in tilesToRender) {
    tileCoord = tilesToRender[key];
    if (this.tileCache_.containsKey(key)) {
      tile = /** @type {HTMLCanvasElement} */ (this.tileCache_.get(key));
    } else {
      tile = /** @type {HTMLCanvasElement} */
          this.tileArchetype_.cloneNode(false);
      tile.getContext('2d').drawImage(sketchCanvas,
          (tileRange.minX - tileCoord.x) * tileSize.width,
          (tileCoord.y - tileRange.maxY) * tileSize.height);
      this.tileCache_.set(key, tile);
    }
    finalContext.drawImage(tile,
        tileSize.width * (tileCoord.x - tileRange.minX),
        tileSize.height * (tileRange.maxY - tileCoord.y));
    this.dirty_ = false;
  }

  this.renderedResolution_ = tileResolution;
  this.renderedExtent_ = tileRangeExtent;
  if (!this.pendingCachePrune_) {
    this.pendingCachePrune_ = true;
    frameState.postRenderFunctions.push(goog.bind(this.pruneTileCache_, this));
  }

};

/**
 * Get rid of tiles that exceed the cache capacity.
 * TODO: add a method to the cache to handle this
 * @private
 */
ol.renderer.canvas.VectorLayer.prototype.pruneTileCache_ = function() {
  while (this.tileCache_.canExpireCache()) {
    this.tileCache_.pop();
  }
  this.pendingCachePrune_ = false;
};

/**
 * @type {number}
 */
ol.renderer.canvas.VectorLayer.TILECACHE_SIZE = 128;
<|endoftext|>


<commit_before>/*global -$ */
'use strict';
// generated on 2015-06-05 using generator-gulp-webapp 0.3.0
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var browserSync = require('browser-sync');
var reload = browserSync.reload;
var del = require('del');
var mainBowerFiles = require('main-bower-files');
var fs = require('fs');
var semver = require('semver');
var pkg = (function () {
  return JSON.parse(fs.readFileSync('./package.json', 'utf8'));
})();

gulp.task('styles', function () {
  return gulp.src('app/styles/main.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      outputStyle: 'nested', // libsass doesn't support expanded yet
      precision: 10,
      includePaths: ['.'],
      onError: console.error.bind(console, 'Sass error:')
    }))
    .pipe($.postcss([
      require('autoprefixer-core')({browsers: ['last 4 versions']})
    ]))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({stream: true}));
});

gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

gulp.task('html', ['styles'], function () {
  var assets = $.useref.assets({searchPath: ['.tmp', 'app', '.']});

  return gulp.src('app/*.html')
    .pipe(assets)
    .pipe($.if('*.js', $.uglify()))
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe($.if('*.html', $.minifyHtml({conditionals: true, loose: true})))
    .pipe(gulp.dest('dist'));
});

gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true,
      // don't remove IDs from SVGs, they are often used
      // as hooks for embedding and styling
      svgoPlugins: [{cleanupIDs: false}]
    })))
    .pipe(gulp.dest('dist/images'));
});

gulp.task('fonts', function () {
  return gulp.src(mainBowerFiles({
    filter: '**/*.{eot,svg,ttf,woff,woff2}',
    debugging: false
  }).concat('app/fonts/**/*'))
    .pipe(gulp.dest('.tmp/fonts'))
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('extras', function () {
  return gulp.src([
    'app/*.*',
    'app/CNAME',
    '!app/*.html'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

gulp.task('serve', ['styles', 'fonts'], function () {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['.tmp', 'app'],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  // watch for changes
  gulp.watch([
    'app/*.html',
    'app/scripts/**/*.js',
    'app/images/**/*',
    '.tmp/fonts/**/*'
  ]).on('change', reload);

  gulp.watch('app/styles/**/*.scss', ['styles']);
  gulp.watch('app/fonts/**/*', ['fonts']);
  gulp.watch('bower.json', ['wiredep', 'fonts']);
});

// inject bower components
gulp.task('wiredep', function () {
  var wiredep = require('wiredep').stream;

  gulp.src('app/styles/*.scss')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});

gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () {
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('default', ['clean'], function () {
  gulp.start('build');
});

gulp.task('gitSemver', function () {

  return gulp.src(['app/manifest.json', 'bower.json', 'package.json'])
    .pipe($.git.commit('Update semver to v'+pkg.version))
    .pipe($.git.push('origin', 'master'));
});

// bump versions on package/bower/manifest
gulp.task('bump', function () {

  // increment version
  var newVer = semver.inc(pkg.version, 'patch');

  pkg.version = newVer;

  // uses gulp-filter
  var manifestFilter = $.filter(['manifest.json']);
  var regularJsons = $.filter(['*', '!manifest.json']);

  return gulp.src(['./bower.json', './package.json', './app/manifest.json'])
    .pipe($.bump({
      version: newVer
    }))
    .pipe(manifestFilter)
    .pipe(gulp.dest('./app'))
    .pipe(manifestFilter.restore())
    .pipe(regularJsons)
    .pipe(gulp.dest('./'));
});

gulp.task('upstream', ['build'], function () {

  return gulp.src('dist')
    .pipe($.subtree({
      remote: 'upstream',
      branch: 'master',
      message: 'New build v'+pkg.version
    }))
    // .pipe($.clean());
});

gulp.task('deploy', ['clean', 'bump', 'gitSemver'], function () {
  gulp.start('upstream');
});
<commit_msg>simple deploy task<commit_after>/*global -$ */
'use strict';
// generated on 2015-06-05 using generator-gulp-webapp 0.3.0
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var browserSync = require('browser-sync');
var reload = browserSync.reload;
var del = require('del');
var mainBowerFiles = require('main-bower-files');
var fs = require('fs');
var semver = require('semver');
var pkg = (function () {
  return JSON.parse(fs.readFileSync('./package.json', 'utf8'));
})();

gulp.task('styles', function () {
  return gulp.src('app/styles/main.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      outputStyle: 'nested', // libsass doesn't support expanded yet
      precision: 10,
      includePaths: ['.'],
      onError: console.error.bind(console, 'Sass error:')
    }))
    .pipe($.postcss([
      require('autoprefixer-core')({browsers: ['last 4 versions']})
    ]))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({stream: true}));
});

gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

gulp.task('html', ['styles'], function () {
  var assets = $.useref.assets({searchPath: ['.tmp', 'app', '.']});

  return gulp.src('app/*.html')
    .pipe(assets)
    .pipe($.if('*.js', $.uglify()))
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe($.if('*.html', $.minifyHtml({conditionals: true, loose: true})))
    .pipe(gulp.dest('dist'));
});

gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true,
      // don't remove IDs from SVGs, they are often used
      // as hooks for embedding and styling
      svgoPlugins: [{cleanupIDs: false}]
    })))
    .pipe(gulp.dest('dist/images'));
});

gulp.task('fonts', function () {
  return gulp.src(mainBowerFiles({
    filter: '**/*.{eot,svg,ttf,woff,woff2}',
    debugging: false
  }).concat('app/fonts/**/*'))
    .pipe(gulp.dest('.tmp/fonts'))
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('extras', function () {
  return gulp.src([
    'app/*.*',
    'app/CNAME',
    '!app/*.html'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

gulp.task('serve', ['styles', 'fonts'], function () {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['.tmp', 'app'],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  // watch for changes
  gulp.watch([
    'app/*.html',
    'app/scripts/**/*.js',
    'app/images/**/*',
    '.tmp/fonts/**/*'
  ]).on('change', reload);

  gulp.watch('app/styles/**/*.scss', ['styles']);
  gulp.watch('app/fonts/**/*', ['fonts']);
  gulp.watch('bower.json', ['wiredep', 'fonts']);
});

// inject bower components
gulp.task('wiredep', function () {
  var wiredep = require('wiredep').stream;

  gulp.src('app/styles/*.scss')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});

gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () {
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('default', ['clean'], function () {
  gulp.start('build');
});

gulp.task('gitSemver', function () {

  return gulp.src(['app/manifest.json', 'bower.json', 'package.json'])
    .pipe($.git.commit('Update semver to v'+pkg.version))
    .pipe($.git.push('origin', 'master'));
});

// bump versions on package/bower/manifest
gulp.task('bump', function () {

  // increment version
  var newVer = semver.inc(pkg.version, 'patch');

  pkg.version = newVer;

  // uses gulp-filter
  var manifestFilter = $.filter(['manifest.json']);
  var regularJsons = $.filter(['*', '!manifest.json']);

  return gulp.src(['./bower.json', './package.json', './app/manifest.json'])
    .pipe($.bump({
      version: newVer
    }))
    .pipe(manifestFilter)
    .pipe(gulp.dest('./app'))
    .pipe(manifestFilter.restore())
    .pipe(regularJsons)
    .pipe(gulp.dest('./'));
});

gulp.task('upstream', ['build'], function () {

  return gulp.src('dist')
    .pipe($.subtree({
      remote: 'upstream',
      branch: 'master',
      message: 'New build v'+pkg.version
    }))
    // .pipe($.clean());
});

// gulp.task('deploy', ['clean', 'bump', 'gitSemver'], function () {
gulp.task('deploy', ['clean'], function () {
  gulp.start('upstream');
});
<|endoftext|>


<commit_before>(typeof define === "function" && define.amd && function (m) {
    define("lodash", m);
} ||
 typeof module === "object" && typeof require === "function" && function (m) {
     module.exports = m(require("lodash"));
 } ||
 function (m) { this.samsam = m(_); }
)(function (_) {
    var o = Object.prototype;
    var div = typeof document !== "undefined" && document.createElement("div");

    /**
     * Returns the internal [[Class]] by calling Object.prototype.toString
     * with the provided value as this. Return value is a string, naming the
     * internal class, e.g. "Array"
     */
    function getClass(value) {
        return o.toString.call(value).split(/[ \]]/)[1];
    }

    /**
     * @name samsam.isElement
     * @param Object object
     *
     * Returns ``true`` if ``object`` is a DOM element node. Unlike
     * Underscore.js/lodash, this function will return ``false`` if ``object``
     * is an *element-like* object, i.e. a regular object with a ``nodeType``
     * property that holds the value ``1``.
     */
    function isElement(object) {
        if (!object || object.nodeType !== 1 || !div) { return false; }
        try {
            object.appendChild(div);
            object.removeChild(div);
        } catch (e) {
            return false;
        }
        return true;
    }

    /**
     * @name samsam.isNaN
     * @param Object value
     *
     * Returns ``true`` if passed in value is ``NaN``. Unlike the globally
     * available ``isNaN``, this method does not attempt to coerce its
     * argument to a number, instead it checks that the number is
     * equal to itself.
     */
    function isNaN(value) {
        // typeof check avoids IE host object issues, hat tip to
        // lodash
        return typeof value === "number" && value !== value;
    }

    /**
     * @name samsam.isNegZero
     * @param Object value
     *
     * Returns ``true`` if ``value`` is ``-0``.
     */
    function isNegZero(value) {
        return value === 0 && 1 / value === -Infinity;
    }

    /**
     * @name samsam.equal
     * @param Object obj1
     * @param Object obj2
     *
     * Returns ``true`` if two objects are strictly equal. Compared to
     * ``===`` there are two exceptions:
     *
     *   - NaN is considered equal to NaN
     *   - -0 and +0 are not considered equal
     */
    function identical(obj1, obj2) {
        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
        }
    }

    /**
     * @name samsam.deepEqual
     * @param Object expected
     *
     * Deep equal comparison. Two values are "deep equal" if:
     *
     *   - They are equal, according to samsam.identical
     *   - They are both date objects representing the same time
     *   - They are both arrays containing elements that are all deepEqual
     *   - They are objects with the same set of properties, and each property
     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
     */
    function deepEqual(obj1, obj2) {
        var type1 = typeof obj1;
        var type2 = typeof obj2;

        if (obj1 === obj2 ||
            isNaN(obj1) || isNaN(obj2) ||
            obj1 == null || obj2 == null || // == null also matches undefined
            type1 !== "object" || type2 !== "object") {
            return identical(obj1, obj2);
        }

        // Elements are only equal if identical(expected, actual)
        if (isElement(obj1) || isElement(obj2)) { return false; }

        var isDate1 = _.isDate(obj1), isDate2 = _.isDate(obj2);
        if (isDate1 || isDate2) {
            if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
                return false;
            }
        }

        if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
            if (obj1.toString() !== obj2.toString()) { return false; }
        }

        var class1 = getClass(obj1);
        var class2 = getClass(obj2);
        var keys1 = _.keys(obj1);
        var keys2 = _.keys(obj2);

        if (_.isArguments(obj1) || _.isArguments(obj2)) {
            if (obj1.length !== obj2.length) { return false; }
        } else {
            if (type1 !== type2 || class1 !== class2 ||
                keys1.length !== keys2.length) {
                return false;
            }
        }

        var key, i, l;

        for (i = 0, l = keys1.length; i < l; i++) {
            key = keys1[i];
            if (!o.hasOwnProperty.call(obj2, key) ||
                !deepEqual(obj1[key], obj2[key])) {
                return false;
            }
        }

        return true;
    }

    function arrayContains(array, subset) {
        var i, l, j, k;
        for (i = 0, l = array.length; i < l; ++i) {
            if (match(array[i], subset[0])) {
                for (j = 0, k = subset.length; j < k; ++j) {
                    if (!match(array[i + j], subset[j])) { return false; }
                }
                return true;
            }
        }
        return false;
    }

    /**
     * @name samsam.match
     * @param Object object
     * @param Object matcher
     *
     * Compare arbitrary value ``object`` with matcher.
     */
    function match(object, matcher) {
        if (matcher && typeof matcher.test === "function") {
            return matcher.test(object);
        }

        if (typeof matcher === "function") {
            return matcher(object) === true;
        }

        if (typeof matcher === "string") {
            matcher = matcher.toLowerCase();
            var notNull = typeof object === "string" || !!object;
            return notNull && ("" + object).toLowerCase().indexOf(matcher) >= 0;
        }

        if (typeof matcher === "number") {
            return matcher == object;
        }

        if (typeof matcher === "boolean") {
            return matcher === object;
        }

        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
            return arrayContains(object, matcher);
        }

        if (matcher && typeof matcher === "object") {
            for (var prop in matcher) {
                if (!match(object[prop], matcher[prop])) {
                    return false;
                }
            }
            return true;
        }

        throw new Error("Matcher was not a string, a number, a " +
                        "function, a boolean or an object");
    }

    return {
        isElement: isElement,
        isNaN: isNaN,
        isNegZero: isNegZero,
        identical: identical,
        deepEqual: deepEqual,
        match: match
    };
});
<commit_msg>More broken doc strings<commit_after>(typeof define === "function" && define.amd && function (m) {
    define("lodash", m);
} ||
 typeof module === "object" && typeof require === "function" && function (m) {
     module.exports = m(require("lodash"));
 } ||
 function (m) { this.samsam = m(_); }
)(function (_) {
    var o = Object.prototype;
    var div = typeof document !== "undefined" && document.createElement("div");

    /**
     * Returns the internal [[Class]] by calling Object.prototype.toString
     * with the provided value as this. Return value is a string, naming the
     * internal class, e.g. "Array"
     */
    function getClass(value) {
        return o.toString.call(value).split(/[ \]]/)[1];
    }

    /**
     * @name samsam.isElement
     * @param Object object
     *
     * Returns ``true`` if ``object`` is a DOM element node. Unlike
     * Underscore.js/lodash, this function will return ``false`` if ``object``
     * is an *element-like* object, i.e. a regular object with a ``nodeType``
     * property that holds the value ``1``.
     */
    function isElement(object) {
        if (!object || object.nodeType !== 1 || !div) { return false; }
        try {
            object.appendChild(div);
            object.removeChild(div);
        } catch (e) {
            return false;
        }
        return true;
    }

    /**
     * @name samsam.isNaN
     * @param Object value
     *
     * Returns ``true`` if passed in value is ``NaN``. Unlike the globally
     * available ``isNaN``, this method does not attempt to coerce its
     * argument to a number, instead it checks that the number is
     * equal to itself.
     */
    function isNaN(value) {
        // typeof check avoids IE host object issues, hat tip to
        // lodash
        return typeof value === "number" && value !== value;
    }

    /**
     * @name samsam.isNegZero
     * @param Object value
     *
     * Returns ``true`` if ``value`` is ``-0``.
     */
    function isNegZero(value) {
        return value === 0 && 1 / value === -Infinity;
    }

    /**
     * @name samsam.equal
     * @param Object obj1
     * @param Object obj2
     *
     * Returns ``true`` if two objects are strictly equal. Compared to
     * ``===`` there are two exceptions:
     *
     *   - NaN is considered equal to NaN
     *   - -0 and +0 are not considered equal
     */
    function identical(obj1, obj2) {
        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
        }
    }

    /**
     * @name samsam.deepEqual
     * @param Object obj1
     * @param Object obj2
     *
     * Deep equal comparison. Two values are "deep equal" if:
     *
     *   - They are equal, according to samsam.identical
     *   - They are both date objects representing the same time
     *   - They are both arrays containing elements that are all deepEqual
     *   - They are objects with the same set of properties, and each property
     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
     */
    function deepEqual(obj1, obj2) {
        var type1 = typeof obj1;
        var type2 = typeof obj2;

        if (obj1 === obj2 ||
            isNaN(obj1) || isNaN(obj2) ||
            obj1 == null || obj2 == null || // == null also matches undefined
            type1 !== "object" || type2 !== "object") {
            return identical(obj1, obj2);
        }

        // Elements are only equal if identical(expected, actual)
        if (isElement(obj1) || isElement(obj2)) { return false; }

        var isDate1 = _.isDate(obj1), isDate2 = _.isDate(obj2);
        if (isDate1 || isDate2) {
            if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
                return false;
            }
        }

        if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
            if (obj1.toString() !== obj2.toString()) { return false; }
        }

        var class1 = getClass(obj1);
        var class2 = getClass(obj2);
        var keys1 = _.keys(obj1);
        var keys2 = _.keys(obj2);

        if (_.isArguments(obj1) || _.isArguments(obj2)) {
            if (obj1.length !== obj2.length) { return false; }
        } else {
            if (type1 !== type2 || class1 !== class2 ||
                keys1.length !== keys2.length) {
                return false;
            }
        }

        var key, i, l;

        for (i = 0, l = keys1.length; i < l; i++) {
            key = keys1[i];
            if (!o.hasOwnProperty.call(obj2, key) ||
                !deepEqual(obj1[key], obj2[key])) {
                return false;
            }
        }

        return true;
    }

    function arrayContains(array, subset) {
        var i, l, j, k;
        for (i = 0, l = array.length; i < l; ++i) {
            if (match(array[i], subset[0])) {
                for (j = 0, k = subset.length; j < k; ++j) {
                    if (!match(array[i + j], subset[j])) { return false; }
                }
                return true;
            }
        }
        return false;
    }

    /**
     * @name samsam.match
     * @param Object object
     * @param Object matcher
     *
     * Compare arbitrary value ``object`` with matcher.
     */
    function match(object, matcher) {
        if (matcher && typeof matcher.test === "function") {
            return matcher.test(object);
        }

        if (typeof matcher === "function") {
            return matcher(object) === true;
        }

        if (typeof matcher === "string") {
            matcher = matcher.toLowerCase();
            var notNull = typeof object === "string" || !!object;
            return notNull && ("" + object).toLowerCase().indexOf(matcher) >= 0;
        }

        if (typeof matcher === "number") {
            return matcher == object;
        }

        if (typeof matcher === "boolean") {
            return matcher === object;
        }

        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
            return arrayContains(object, matcher);
        }

        if (matcher && typeof matcher === "object") {
            for (var prop in matcher) {
                if (!match(object[prop], matcher[prop])) {
                    return false;
                }
            }
            return true;
        }

        throw new Error("Matcher was not a string, a number, a " +
                        "function, a boolean or an object");
    }

    return {
        isElement: isElement,
        isNaN: isNaN,
        isNegZero: isNegZero,
        identical: identical,
        deepEqual: deepEqual,
        match: match
    };
});
<|endoftext|>


<commit_before>var Twitter = require('twit');
var twit = new Twitter({
    consumer_key: process.env.TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    access_token: process.env.ACCESS_TOKEN,
    access_token_secret: process.env.ACCESS_TOKEN_SECRET
});

var userStream = twit.stream('user', {with: 'user', replies: 'all'});

userStream.on('tweet', function(tweet) {
  twit.post('statuses/retweet/:id', {id: tweet.id}, function(err, reply) {
    console.log(err, reply);
  });
});
<commit_msg>Factor out a retweet function. Realize that Tweet IDs need to be strings.<commit_after>var Twitter = require('twit');
var twit = new Twitter({
    consumer_key: process.env.TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    access_token: process.env.ACCESS_TOKEN,
    access_token_secret: process.env.ACCESS_TOKEN_SECRET
});

var userStream = twit.stream('user', { with: 'user', replies: 'all' });

userStream.on('tweet', function(tweet) {
  console.log('received mention');
  retweetById(tweet.id_str);
});

var retweetById = function(idStr) {
  twit.post('statuses/retweet/:id', {id: idStr}, function(err, reply) {
    console.log("retweeted id:" + idStr);
    console.log(err);
    console.log(reply);
  });
};

<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require("vinyl-buffer");
var browserify = require('browserify');
var notify = require("gulp-notify");
var babelify = require('babelify');
var watchify = require('watchify');
var minifyCSS = require('gulp-minify-css');
var browserSync = require('browser-sync').create();

var scriptsDir = './app/';
var cssDir = './css/';
var buildDir = './build/';
var buildScriptDir = './build/js/';
var buildCssDir = './build/css/';
var mainJsFile = 'app.js';

var files = [
    './manifest.json',
    'popup.html',
    'icon.png'
];

var props = { entries: [scriptsDir + mainJsFile], };
var bundler = watchify(browserify(props, watchify.args));

function handleErrors() {
    var args = Array.prototype.slice.call(arguments);
    notify.onError({
        title: "Compile Error",
        message: "<%= error.message %>"
    }).apply(this, args);
    this.emit('end'); // Keep gulp from hanging on this task
}

function bundle() {
    return bundler
        .transform(babelify, {
            "presets": [
                "es2015",
                "react"
            ],
            "plugins": [
                "transform-object-rest-spread",
                "transform-decorators-legacy"
            ]
        })
        .bundle()
        .on('error', handleErrors)
        .pipe(source(mainJsFile))
        .pipe(buffer())
        .pipe(gulp.dest(buildScriptDir));
}

gulp.task('browser-watch', function (done) {
    browserSync.reload();
    done();
});

gulp.task('buildScript', bundle);

gulp.task('buildCss', function() {
    return gulp.src('css/*.css')
        .pipe(minifyCSS())
        .pipe(gulp.dest(buildCssDir));
});

gulp.task('buildOtherFiles', function () {
    files.map(function (entry) {
        return gulp.src(entry)
            .pipe(gulp.dest(buildDir));
    })
});

gulp.task('auto', function () {
    gulp.watch('css/*.css', ['buildCss']);
    gulp.watch(scriptsDir + '**/*.js', ['buildScript']);
    gulp.watch(files, ['buildOtherFiles']);
});

gulp.task('build', ['buildScript', 'buildCss', 'buildOtherFiles']);

gulp.task('default', ['buildScript', 'buildCss', 'buildOtherFiles', 'auto'], function () {
    browserSync.init({
        server: {
            baseDir: "./build/"
        }
    });

    gulp.watch('./build/**').on("change", browserSync.reload);
});<commit_msg>:apple: 修改mac下gulp首页文件定位问题<commit_after>'use strict';

var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require("vinyl-buffer");
var browserify = require('browserify');
var notify = require("gulp-notify");
var babelify = require('babelify');
var watchify = require('watchify');
var minifyCSS = require('gulp-minify-css');
var browserSync = require('browser-sync').create();

var scriptsDir = './app/';
var cssDir = './css/';
var buildDir = './build/';
var buildScriptDir = './build/js/';
var buildCssDir = './build/css/';
var mainJsFile = 'app.js';

var files = [
    './manifest.json',
    'popup.html',
    'icon.png'
];

var props = { entries: [scriptsDir + mainJsFile], };
var bundler = watchify(browserify(props, watchify.args));

function handleErrors() {
    var args = Array.prototype.slice.call(arguments);
    notify.onError({
        title: "Compile Error",
        message: "<%= error.message %>"
    }).apply(this, args);
    this.emit('end'); // Keep gulp from hanging on this task
}

function bundle() {
    return bundler
        .transform(babelify, {
            "presets": [
                "es2015",
                "react"
            ],
            "plugins": [
                "transform-object-rest-spread",
                "transform-decorators-legacy"
            ]
        })
        .bundle()
        .on('error', handleErrors)
        .pipe(source(mainJsFile))
        .pipe(buffer())
        .pipe(gulp.dest(buildScriptDir));
}

gulp.task('browser-watch', function (done) {
    browserSync.reload();
    done();
});

gulp.task('buildScript', bundle);

gulp.task('buildCss', function() {
    return gulp.src('css/*.css')
        .pipe(minifyCSS())
        .pipe(gulp.dest(buildCssDir));
});

gulp.task('buildOtherFiles', function () {
    files.map(function (entry) {
        return gulp.src(entry)
            .pipe(gulp.dest(buildDir));
    })
});

gulp.task('auto', function () {
    gulp.watch('css/*.css', ['buildCss']);
    gulp.watch(scriptsDir + '**/*.js', ['buildScript']);
    gulp.watch(files, ['buildOtherFiles']);
});

gulp.task('build', ['buildScript', 'buildCss', 'buildOtherFiles']);

gulp.task('default', ['buildScript', 'buildCss', 'buildOtherFiles', 'auto'], function () {
    browserSync.init({
        server: {
            baseDir: "./build/",
            index: "popup.html"
        }
    });

    gulp.watch('./build/**').on("change", browserSync.reload);
});<|endoftext|>


<commit_before>goog.provide('ol.renderer.canvas.VectorLayer');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.functions');
goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.Vector');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.vector');
goog.require('ol.style.ImageState');

/**
 * @constructor
 * @extends {ol.renderer.canvas.Layer}
 * @param {ol.renderer.Map} mapRenderer Map renderer.
 * @param {ol.layer.Vector} vectorLayer Vector layer.
 */
ol.renderer.canvas.VectorLayer = function(mapRenderer, vectorLayer) {

  goog.base(this, mapRenderer, vectorLayer);

  /**
   * @private
   * @type {boolean}
   */
  this.dirty_ = false;

  /**
   * @private
   * @type {number}
   */
  this.renderedRevision_ = -1;

  /**
   * @private
   * @type {number}
   */
  this.renderedResolution_ = NaN;

  /**
   * @private
   * @type {number}
   */
  this.renderedRotation_ = NaN;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.renderedExtent_ = ol.extent.createEmpty();

  /**
   * @private
   * @type {ol.render.canvas.ReplayGroup}
   */
  this.replayGroup_ = null;

};
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.composeFrame =
    function(frameState, layerState, context) {

  var transform = this.getTransform(frameState);

  this.dispatchPreComposeEvent(context, frameState, transform);

  var replayGroup = this.replayGroup_;
  if (!goog.isNull(replayGroup)) {
    var renderGeometryFunction = this.getRenderGeometryFunction_();
    goog.asserts.assert(goog.isFunction(renderGeometryFunction));
    context.globalAlpha = layerState.opacity;
    replayGroup.replay(
        context, frameState.extent, transform, renderGeometryFunction);
  }

  this.dispatchPostComposeEvent(context, frameState, transform);

};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel =
    function(pixel, callback, opt_obj) {
  if (goog.isNull(this.replayGroup_)) {
    return undefined;
  } else {
    goog.asserts.assert(!ol.extent.isEmpty(this.renderedExtent_));
    goog.asserts.assert(!isNaN(this.renderedResolution_));
    goog.asserts.assert(!isNaN(this.renderedRotation_));
    var coordinate = this.getMap().getCoordinateFromPixel(pixel);
    var layer = this.getLayer();
    var renderGeometryFunction = this.getRenderGeometryFunction_();
    goog.asserts.assert(goog.isFunction(renderGeometryFunction));
    return this.replayGroup_.forEachGeometryAtCoordinate(this.renderedExtent_,
        this.renderedResolution_, this.renderedRotation_, coordinate,
        renderGeometryFunction,
        /**
         * @param {ol.geom.Geometry} geometry Geometry.
         * @param {Object} data Data.
         */
        function(geometry, data) {
          var feature = /** @type {ol.Feature} */ (data);
          goog.asserts.assert(goog.isDef(feature));
          return callback.call(opt_obj, feature, layer);
        });
  }
};

/**
 * @private
 * @return {function(ol.geom.Geometry): boolean|undefined} Render geometry
 *     function.
 */
ol.renderer.canvas.VectorLayer.prototype.getRenderGeometryFunction_ =
    function() {
  var vectorLayer = this.getVectorLayer();
  var renderGeometryFunction = vectorLayer.getRenderGeometryFunction();
  if (!goog.isDef(renderGeometryFunction)) {
    renderGeometryFunction = goog.functions.TRUE;
  }
  return renderGeometryFunction;
};

/**
 * @return {ol.layer.Vector} Vector layer.
 */
ol.renderer.canvas.VectorLayer.prototype.getVectorLayer = function() {
  return /** @type {ol.layer.Vector} */ (this.getLayer());
};

/**
 * Handle changes in image style state.
 * @param {goog.events.Event} event Image style change event.
 * @private
 */
ol.renderer.canvas.VectorLayer.prototype.handleImageStyleChange_ =
    function(event) {
  var imageStyle = /** @type {ol.style.Image} */ (event.target);
  if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
    this.renderIfReadyAndVisible();
  }
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
    function(frameState, layerState) {

  if (!this.dirty_ && (frameState.viewHints[ol.ViewHint.ANIMATING] ||
      frameState.viewHints[ol.ViewHint.INTERACTING])) {
    return;
  }

  var vectorLayer = this.getVectorLayer();
  var vectorSource = vectorLayer.getVectorSource();
  var frameStateExtent = frameState.extent;
  var frameStateResolution = frameState.view2DState.resolution;
  var pixelRatio = frameState.devicePixelRatio;

  if (!this.dirty_ &&
      this.renderedResolution_ == frameStateResolution &&
      this.renderedRevision_ == vectorSource.getRevision() &&
      ol.extent.containsExtent(this.renderedExtent_, frameStateExtent)) {
    return;
  }

  var extent = this.renderedExtent_;
  var xBuffer = ol.extent.getWidth(frameStateExtent) / 4;
  var yBuffer = ol.extent.getHeight(frameStateExtent) / 4;
  extent[0] = frameStateExtent[0] - xBuffer;
  extent[1] = frameStateExtent[1] - yBuffer;
  extent[2] = frameStateExtent[2] + xBuffer;
  extent[3] = frameStateExtent[3] + yBuffer;

  // FIXME dispose of old replayGroup in post render
  goog.dispose(this.replayGroup_);
  this.replayGroup_ = null;

  this.dirty_ = false;

  var styleFunction = vectorLayer.getStyleFunction();
  if (!goog.isDef(styleFunction)) {
    styleFunction = ol.layer.Vector.defaultStyleFunction;
  }
  var tolerance = frameStateResolution / (2 * pixelRatio);
  var replayGroup = new ol.render.canvas.ReplayGroup(pixelRatio, tolerance);
  vectorSource.forEachFeatureInExtent(extent,
      /**
       * @param {ol.Feature} feature Feature.
       */
      function(feature) {
        this.dirty_ = this.dirty_ ||
            this.renderFeature(feature, frameStateResolution, pixelRatio,
                styleFunction, replayGroup);
      }, this);
  replayGroup.finish();

  this.renderedResolution_ = frameStateResolution;
  this.renderedRevision_ = vectorSource.getRevision();
  this.renderedRotation_ = frameState.view2DState.rotation;
  if (!replayGroup.isEmpty()) {
    this.replayGroup_ = replayGroup;
  }

};

/**
 * @param {ol.Feature} feature Feature.
 * @param {number} resolution Resolution.
 * @param {number} pixelRatio Pixel ratio.
 * @param {ol.style.StyleFunction} styleFunction Style function.
 * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
 * @return {boolean} `true` if an image is loading.
 */
ol.renderer.canvas.VectorLayer.prototype.renderFeature =
    function(feature, resolution, pixelRatio, styleFunction, replayGroup) {
  var loading = false;
  var styles = styleFunction(feature, resolution);
  // FIXME if styles is null, should we use the default style?
  if (!goog.isDefAndNotNull(styles)) {
    return false;
  }
  // simplify to a tolerance of half a device pixel
  var squaredTolerance =
      resolution * resolution / (4 * pixelRatio * pixelRatio);
  var i, ii, style, imageStyle, imageState;
  for (i = 0, ii = styles.length; i < ii; ++i) {
    style = styles[i];
    imageStyle = style.getImage();
    if (!goog.isNull(imageStyle)) {
      if (imageStyle.getImageState() == ol.style.ImageState.IDLE) {
        goog.events.listenOnce(imageStyle, goog.events.EventType.CHANGE,
            this.handleImageStyleChange_, false, this);
        imageStyle.load();
      } else if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
        ol.renderer.vector.renderFeature(
            replayGroup, feature, style, squaredTolerance, feature);
      }
      goog.asserts.assert(
          imageStyle.getImageState() != ol.style.ImageState.IDLE);
      loading = imageStyle.getImageState() == ol.style.ImageState.LOADING;
    } else {
      ol.renderer.vector.renderFeature(
          replayGroup, feature, style, squaredTolerance, feature);
    }
  }
  return loading;
};
<commit_msg>Only hit-detect visible features<commit_after>goog.provide('ol.renderer.canvas.VectorLayer');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.functions');
goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.Vector');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.vector');
goog.require('ol.style.ImageState');

/**
 * @constructor
 * @extends {ol.renderer.canvas.Layer}
 * @param {ol.renderer.Map} mapRenderer Map renderer.
 * @param {ol.layer.Vector} vectorLayer Vector layer.
 */
ol.renderer.canvas.VectorLayer = function(mapRenderer, vectorLayer) {

  goog.base(this, mapRenderer, vectorLayer);

  /**
   * @private
   * @type {boolean}
   */
  this.dirty_ = false;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.frameStateExtent_ = ol.extent.createEmpty();

  /**
   * @private
   * @type {number}
   */
  this.renderedRevision_ = -1;

  /**
   * @private
   * @type {number}
   */
  this.renderedResolution_ = NaN;

  /**
   * @private
   * @type {number}
   */
  this.renderedRotation_ = NaN;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.renderedExtent_ = ol.extent.createEmpty();

  /**
   * @private
   * @type {ol.render.canvas.ReplayGroup}
   */
  this.replayGroup_ = null;

};
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.composeFrame =
    function(frameState, layerState, context) {

  var transform = this.getTransform(frameState);

  this.dispatchPreComposeEvent(context, frameState, transform);

  var replayGroup = this.replayGroup_;
  if (!goog.isNull(replayGroup)) {
    var renderGeometryFunction = this.getRenderGeometryFunction_();
    goog.asserts.assert(goog.isFunction(renderGeometryFunction));
    context.globalAlpha = layerState.opacity;
    replayGroup.replay(
        context, frameState.extent, transform, renderGeometryFunction);
  }

  this.dispatchPostComposeEvent(context, frameState, transform);

};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel =
    function(pixel, callback, opt_obj) {
  if (goog.isNull(this.replayGroup_)) {
    return undefined;
  } else {
    goog.asserts.assert(!ol.extent.isEmpty(this.frameStateExtent_));
    goog.asserts.assert(!isNaN(this.renderedResolution_));
    goog.asserts.assert(!isNaN(this.renderedRotation_));
    var coordinate = this.getMap().getCoordinateFromPixel(pixel);
    var layer = this.getLayer();
    var renderGeometryFunction = this.getRenderGeometryFunction_();
    goog.asserts.assert(goog.isFunction(renderGeometryFunction));
    return this.replayGroup_.forEachGeometryAtCoordinate(this.frameStateExtent_,
        this.renderedResolution_, this.renderedRotation_, coordinate,
        renderGeometryFunction,
        /**
         * @param {ol.geom.Geometry} geometry Geometry.
         * @param {Object} data Data.
         */
        function(geometry, data) {
          var feature = /** @type {ol.Feature} */ (data);
          goog.asserts.assert(goog.isDef(feature));
          return callback.call(opt_obj, feature, layer);
        });
  }
};

/**
 * @private
 * @return {function(ol.geom.Geometry): boolean|undefined} Render geometry
 *     function.
 */
ol.renderer.canvas.VectorLayer.prototype.getRenderGeometryFunction_ =
    function() {
  var vectorLayer = this.getVectorLayer();
  var renderGeometryFunction = vectorLayer.getRenderGeometryFunction();
  if (!goog.isDef(renderGeometryFunction)) {
    renderGeometryFunction = goog.functions.TRUE;
  }
  return renderGeometryFunction;
};

/**
 * @return {ol.layer.Vector} Vector layer.
 */
ol.renderer.canvas.VectorLayer.prototype.getVectorLayer = function() {
  return /** @type {ol.layer.Vector} */ (this.getLayer());
};

/**
 * Handle changes in image style state.
 * @param {goog.events.Event} event Image style change event.
 * @private
 */
ol.renderer.canvas.VectorLayer.prototype.handleImageStyleChange_ =
    function(event) {
  var imageStyle = /** @type {ol.style.Image} */ (event.target);
  if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
    this.renderIfReadyAndVisible();
  }
};

/**
 * @inheritDoc
 */
ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
    function(frameState, layerState) {

  if (!this.dirty_ && (frameState.viewHints[ol.ViewHint.ANIMATING] ||
      frameState.viewHints[ol.ViewHint.INTERACTING])) {
    return;
  }

  var vectorLayer = this.getVectorLayer();
  var vectorSource = vectorLayer.getVectorSource();
  var frameStateExtent = frameState.extent;
  var frameStateResolution = frameState.view2DState.resolution;
  var pixelRatio = frameState.devicePixelRatio;

  this.frameStateExtent_ = frameStateExtent;

  if (!this.dirty_ &&
      this.renderedResolution_ == frameStateResolution &&
      this.renderedRevision_ == vectorSource.getRevision() &&
      ol.extent.containsExtent(this.renderedExtent_, frameStateExtent)) {
    return;
  }

  var extent = this.renderedExtent_;
  var xBuffer = ol.extent.getWidth(frameStateExtent) / 4;
  var yBuffer = ol.extent.getHeight(frameStateExtent) / 4;
  extent[0] = frameStateExtent[0] - xBuffer;
  extent[1] = frameStateExtent[1] - yBuffer;
  extent[2] = frameStateExtent[2] + xBuffer;
  extent[3] = frameStateExtent[3] + yBuffer;

  // FIXME dispose of old replayGroup in post render
  goog.dispose(this.replayGroup_);
  this.replayGroup_ = null;

  this.dirty_ = false;

  var styleFunction = vectorLayer.getStyleFunction();
  if (!goog.isDef(styleFunction)) {
    styleFunction = ol.layer.Vector.defaultStyleFunction;
  }
  var tolerance = frameStateResolution / (2 * pixelRatio);
  var replayGroup = new ol.render.canvas.ReplayGroup(pixelRatio, tolerance);
  vectorSource.forEachFeatureInExtent(extent,
      /**
       * @param {ol.Feature} feature Feature.
       */
      function(feature) {
        this.dirty_ = this.dirty_ ||
            this.renderFeature(feature, frameStateResolution, pixelRatio,
                styleFunction, replayGroup);
      }, this);
  replayGroup.finish();

  this.renderedResolution_ = frameStateResolution;
  this.renderedRevision_ = vectorSource.getRevision();
  this.renderedRotation_ = frameState.view2DState.rotation;
  if (!replayGroup.isEmpty()) {
    this.replayGroup_ = replayGroup;
  }

};

/**
 * @param {ol.Feature} feature Feature.
 * @param {number} resolution Resolution.
 * @param {number} pixelRatio Pixel ratio.
 * @param {ol.style.StyleFunction} styleFunction Style function.
 * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
 * @return {boolean} `true` if an image is loading.
 */
ol.renderer.canvas.VectorLayer.prototype.renderFeature =
    function(feature, resolution, pixelRatio, styleFunction, replayGroup) {
  var loading = false;
  var styles = styleFunction(feature, resolution);
  // FIXME if styles is null, should we use the default style?
  if (!goog.isDefAndNotNull(styles)) {
    return false;
  }
  // simplify to a tolerance of half a device pixel
  var squaredTolerance =
      resolution * resolution / (4 * pixelRatio * pixelRatio);
  var i, ii, style, imageStyle, imageState;
  for (i = 0, ii = styles.length; i < ii; ++i) {
    style = styles[i];
    imageStyle = style.getImage();
    if (!goog.isNull(imageStyle)) {
      if (imageStyle.getImageState() == ol.style.ImageState.IDLE) {
        goog.events.listenOnce(imageStyle, goog.events.EventType.CHANGE,
            this.handleImageStyleChange_, false, this);
        imageStyle.load();
      } else if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
        ol.renderer.vector.renderFeature(
            replayGroup, feature, style, squaredTolerance, feature);
      }
      goog.asserts.assert(
          imageStyle.getImageState() != ol.style.ImageState.IDLE);
      loading = imageStyle.getImageState() == ol.style.ImageState.LOADING;
    } else {
      ol.renderer.vector.renderFeature(
          replayGroup, feature, style, squaredTolerance, feature);
    }
  }
  return loading;
};
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var buffer = require('vinyl-buffer');
var reload = browserSync.reload;
var merge = require('merge-stream');
var path = require('path');
var fs = require('fs');
var glob = require('glob');
var globby = require('globby');
var mocha = require('gulp-mocha');
var through = require('through2');
var rename = require('gulp-rename');
var historyApiFallback = require('connect-history-api-fallback');
var useref = require('gulp-useref');
var gutil = require('gulp-util');

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

var styleTask = function (stylesPath, srcs) {
  return gulp.src(srcs.map(function(src) {
      return path.join('app', stylesPath, src);
    }))
    .pipe($.changed(stylesPath, {extension: '.css'}))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/' + stylesPath))
    .pipe($.if('*.css', $.cssmin()))
    .pipe(gulp.dest('dist/' + stylesPath))
    .pipe($.size({title: stylesPath}));
};

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function () {
  return styleTask('styles', ['**/*.css']);
});

gulp.task('elements', function () {
  return styleTask('elements', ['**/*.css']);
});

// Browserify npm modules
gulp.task('browserify', function () {

  return browserify('app/scripts/app.js')
    .bundle()
    //Pass desired output filename to vinyl-source-stream
    .pipe(source('bundle.js'))
    // Uglify
    //.pipe(streamify($.uglify()))
    // Start piping stream to tasks!
    .pipe(gulp.dest('./app/scripts/'));
});

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src([
      'app/scripts/**/*.js',
      '!app/scripts/adapters/**/*.js',
      '!app/scripts/vendor/**/*.js',
      'app/elements/**/*.js',
      'app/elements/**/*.html'
    ])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint.extract()) // Extract JS from .html files
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    /*.pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))*/
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy All Files At The Root Level (app)
gulp.task('copy', function () {
  var app = gulp.src([
    'app/*',
    '!app/test',
    '!app/precache.json'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));

  var bower = gulp.src([
    'bower_components/**/*'
  ]).pipe(gulp.dest('dist/bower_components'));

  var elements = gulp.src(['app/elements/**/*'])
    .pipe(gulp.dest('dist/elements'));

  var images = gulp.src(['app/images/**/*'])
    .pipe(gulp.dest('dist/images'));

  var swBootstrap = gulp.src(['bower_components/platinum-sw/bootstrap/*.js'])
    .pipe(gulp.dest('dist/elements/bootstrap'));

  var swToolbox = gulp.src(['bower_components/sw-toolbox/*.js'])
    .pipe(gulp.dest('dist/sw-toolbox'));

  var vendorScripts = gulp.src(['app/scripts/vendor/**/*'])
    .pipe(gulp.dest('dist/scripts/vendor'));

  var vendorStyles = gulp.src(['app/styles/vendor/**/*'])
    .pipe(gulp.dest('dist/styles/vendor'));

  var vulcanized = gulp.src(['app/elements/elements.html'])
    .pipe($.rename('elements.vulcanized.html'))
    .pipe(gulp.dest('dist/elements'));

  var testMedia = gulp.src(['app/testmedia/**/*'])
    .pipe(gulp.dest('dist/testmedia'));

  var profiles = gulp.src(['app/profiles/**/*'])
    .pipe(gulp.dest('dist/profiles'));

  var fonts = gulp.src(['app/fonts/**/*'])
    .pipe(gulp.dest('dist/fonts'));

  return merge(app, bower, elements, vulcanized, swBootstrap, swToolbox, testMedia, profiles, vendorScripts, vendorStyles, fonts)
    .pipe($.size({title: 'copy'}));
});

// Copy Web Fonts To Dist
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function () {

  var assets = useref.assets({searchPath: ['.tmp', 'app', 'dist']});

  return gulp.src(['app/**/*.html', '!app/{elements,test}/**/*.html'])
    // Replace path for vulcanized assets
    .pipe($.if('*.html', $.replace('elements/elements.html', 'elements/elements.vulcanized.html')))
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'}).on('error', gutil.log)))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.cssmin()))
    .pipe(assets.restore())
    .pipe(useref())
    // Minify Any HTML
    .pipe($.if('*.html', $.minifyHtml({
      quotes: true,
      empty: true,
      spare: true
    })))
    // Output Files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Vulcanize imports
gulp.task('vulcanize', function () {
  var DEST_DIR = 'dist/elements';

  return gulp.src('dist/elements/elements.vulcanized.html')
    .pipe($.vulcanize({
      stripComments: true,
      inlineCss: true,
      inlineScripts: true
    }))
    .pipe(gulp.dest(DEST_DIR))
    .pipe($.size({title: 'vulcanize'}));
});

// Generate a list of files that should be precached when serving from 'dist'.
// The list will be consumed by the <platinum-sw-cache> element.
gulp.task('precache', function (callback) {
  var dir = 'dist';

  glob('{elements,scripts,styles}/**/*.*', {cwd: dir}, function(error, files) {
    if (error) {
      callback(error);
    } else {
      files.push('online.html', 'offline.html', './', 'bower_components/webcomponentsjs/webcomponents-lite.min.js');
      var filePath = path.join(dir, 'precache.json');
      fs.writeFile(filePath, JSON.stringify(files), callback);
    }
  });
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

// Watch Files For Changes & Reload
gulp.task('serve', ['styles', 'elements', 'images'], function () {
  browserSync({
    notify: false,
    logPrefix: 'PSK',
    snippetOptions: {
      rule: {
        match: '',
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    // will present a certificate warning in the browser.
    // https: true,
    server: {
      baseDir: ['.tmp', 'app'],
      middleware: [ historyApiFallback() ],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch(['app/**/*.html'], reload);
  gulp.watch(['app/styles/**/*.css'], ['styles', reload]);
  gulp.watch(['app/elements/**/*.css'], ['elements', reload]);
  gulp.watch(['app/{scripts,elements}/**/*.js', '!app/scripts/bundle.js'], ['browserify']);
  gulp.watch(['app/scripts/bundle.js'], ['jshint', reload]);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function () {
  browserSync({
    notify: false,
    logPrefix: 'PSK',
    snippetOptions: {
      rule: {
        match: '',
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    // will present a certificate warning in the browser.
    // https: true,
    server: 'dist',
    middleware: [ historyApiFallback() ]
  });
});

gulp.task("browser-unit-tests", function () {

  "use strict";

  browserSync({
    server: {
      //serve tests and the root as base dirs
      baseDir: ["./app/test/", "./"],
      index: "testrunner.html"
    }
  });
});

gulp.task('unit-tests', function () {

  // gulp expects tasks to return a stream, so we create one here.
  var bundledStream = through();

  bundledStream
    // turns the output bundle stream into a stream containing
    // the normal attributes gulp plugins expect.
    .pipe(source('stores-test.js'))
    // the rest of the gulp task, as you would normally write it.
    .pipe(buffer())
    .pipe(gulp.dest('./app/test/scripts/build/'))
    .pipe(mocha({
      bail: false,
      reporter: 'doc'
    }));

  // "globby" replaces the normal "gulp.src" as Browserify
  // creates it's own readable stream.
  globby(['./app/test/scripts/specs/*.js'], function(err, entries) {
    // ensure any errors from globby are handled
    if (err) {
      bundledStream.emit('error', err);
      return;
    }

    // create the Browserify instance and pipe the Browserify stream into the stream we created earlier
    // this starts our gulp pipeline.
    browserify({
      entries: entries
    })
    .ignore('browserify-fs')
    .bundle()
    .pipe(bundledStream);
  });

  // finally, we return the stream, so gulp knows when this task is done.
  return bundledStream;
});

// Build Production Files, the Default Task
gulp.task('default', ['clean'], function (cb) {
  runSequence(
    'browserify',
    ['copy', 'styles'],
    'elements',
    ['jshint', 'images', 'fonts', 'html', /*'unit-tests'*/],
    //'vulcanize',
    cb);
    // Note: add , 'precache' , after 'vulcanize', if your are going to use Service Worker
});

// Load tasks for web-component-tester
// Adds tasks for `gulp test:local` and `gulp test:remote`
//require('web-component-tester').gulp.init(gulp);

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<commit_msg>Using electron packager to package on OSX<commit_after>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var buffer = require('vinyl-buffer');
var reload = browserSync.reload;
var merge = require('merge-stream');
var path = require('path');
var fs = require('fs');
var glob = require('glob');
var globby = require('globby');
var mocha = require('gulp-mocha');
var through = require('through2');
var rename = require('gulp-rename');
var historyApiFallback = require('connect-history-api-fallback');
var useref = require('gulp-useref');
var gutil = require('gulp-util');
var packager = require('electron-packager');

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

var styleTask = function (stylesPath, srcs) {
  return gulp.src(srcs.map(function(src) {
      return path.join('app', stylesPath, src);
    }))
    .pipe($.changed(stylesPath, {extension: '.css'}))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/' + stylesPath))
    .pipe($.if('*.css', $.cssmin()))
    .pipe(gulp.dest('dist/' + stylesPath))
    .pipe($.size({title: stylesPath}));
};

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function () {
  return styleTask('styles', ['**/*.css']);
});

gulp.task('elements', function () {
  return styleTask('elements', ['**/*.css']);
});

// Browserify npm modules
gulp.task('browserify', function () {

  return browserify('app/scripts/app.js')
    .bundle()
    //Pass desired output filename to vinyl-source-stream
    .pipe(source('bundle.js'))
    // Uglify
    //.pipe(streamify($.uglify()))
    // Start piping stream to tasks!
    .pipe(gulp.dest('./app/scripts/'));
});

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src([
      'app/scripts/**/*.js',
      '!app/scripts/adapters/**/*.js',
      '!app/scripts/vendor/**/*.js',
      'app/elements/**/*.js',
      'app/elements/**/*.html'
    ])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint.extract()) // Extract JS from .html files
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    /*.pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))*/
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy All Files At The Root Level (app)
gulp.task('copy', function () {
  var app = gulp.src([
    'app/*',
    '!app/test',
    '!app/precache.json'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));

  var bower = gulp.src([
    'bower_components/**/*'
  ]).pipe(gulp.dest('dist/bower_components'));

  var elements = gulp.src(['app/elements/**/*'])
    .pipe(gulp.dest('dist/elements'));

  var images = gulp.src(['app/images/**/*'])
    .pipe(gulp.dest('dist/images'));

  var swBootstrap = gulp.src(['bower_components/platinum-sw/bootstrap/*.js'])
    .pipe(gulp.dest('dist/elements/bootstrap'));

  var swToolbox = gulp.src(['bower_components/sw-toolbox/*.js'])
    .pipe(gulp.dest('dist/sw-toolbox'));

  var vendorScripts = gulp.src(['app/scripts/vendor/**/*'])
    .pipe(gulp.dest('dist/scripts/vendor'));

  var vendorStyles = gulp.src(['app/styles/vendor/**/*'])
    .pipe(gulp.dest('dist/styles/vendor'));

  var vulcanized = gulp.src(['app/elements/elements.html'])
    .pipe($.rename('elements.vulcanized.html'))
    .pipe(gulp.dest('dist/elements'));

  var testMedia = gulp.src(['app/testmedia/**/*'])
    .pipe(gulp.dest('dist/testmedia'));

  var profiles = gulp.src(['app/profiles/**/*'])
    .pipe(gulp.dest('dist/profiles'));

  var fonts = gulp.src(['app/fonts/**/*'])
    .pipe(gulp.dest('dist/fonts'));

  return merge(app, bower, elements, vulcanized, swBootstrap, swToolbox, testMedia, profiles, vendorScripts, vendorStyles, fonts)
    .pipe($.size({title: 'copy'}));
});

// Copy Web Fonts To Dist
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function () {

  var assets = useref.assets({searchPath: ['.tmp', 'app', 'dist']});

  return gulp.src(['app/**/*.html', '!app/{elements,test}/**/*.html'])
    // Replace path for vulcanized assets
    .pipe($.if('*.html', $.replace('elements/elements.html', 'elements/elements.vulcanized.html')))
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'}).on('error', gutil.log)))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.cssmin()))
    .pipe(assets.restore())
    .pipe(useref())
    // Minify Any HTML
    .pipe($.if('*.html', $.minifyHtml({
      quotes: true,
      empty: true,
      spare: true
    })))
    // Output Files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Vulcanize imports
gulp.task('vulcanize', function () {
  var DEST_DIR = 'dist/elements';

  return gulp.src('dist/elements/elements.vulcanized.html')
    .pipe($.vulcanize({
      stripComments: true,
      inlineCss: true,
      inlineScripts: true
    }))
    .pipe(gulp.dest(DEST_DIR))
    .pipe($.size({title: 'vulcanize'}));
});

// Generate a list of files that should be precached when serving from 'dist'.
// The list will be consumed by the <platinum-sw-cache> element.
gulp.task('precache', function (callback) {
  var dir = 'dist';

  glob('{elements,scripts,styles}/**/*.*', {cwd: dir}, function(error, files) {
    if (error) {
      callback(error);
    } else {
      files.push('online.html', 'offline.html', './', 'bower_components/webcomponentsjs/webcomponents-lite.min.js');
      var filePath = path.join(dir, 'precache.json');
      fs.writeFile(filePath, JSON.stringify(files), callback);
    }
  });
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

// Watch Files For Changes & Reload
gulp.task('serve', ['styles', 'elements', 'images'], function () {
  browserSync({
    notify: false,
    logPrefix: 'PSK',
    snippetOptions: {
      rule: {
        match: '',
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    // will present a certificate warning in the browser.
    // https: true,
    server: {
      baseDir: ['.tmp', 'app'],
      middleware: [ historyApiFallback() ],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch(['app/**/*.html'], reload);
  gulp.watch(['app/styles/**/*.css'], ['styles', reload]);
  gulp.watch(['app/elements/**/*.css'], ['elements', reload]);
  gulp.watch(['app/{scripts,elements}/**/*.js', '!app/scripts/bundle.js'], ['browserify']);
  gulp.watch(['app/scripts/bundle.js'], ['jshint', reload]);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function () {
  browserSync({
    notify: false,
    logPrefix: 'PSK',
    snippetOptions: {
      rule: {
        match: '',
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    // will present a certificate warning in the browser.
    // https: true,
    server: 'dist',
    middleware: [ historyApiFallback() ]
  });
});

gulp.task("browser-unit-tests", function () {

  "use strict";

  browserSync({
    server: {
      //serve tests and the root as base dirs
      baseDir: ["./app/test/", "./"],
      index: "testrunner.html"
    }
  });
});

gulp.task('packager:osxonline', function () {

  var options = {
    'app-version': '1.0',
    'asar': true,
    'arch': 'all',
    'dir': './app',
    'icon': './icons/SITFonline.ico.icns',
    'platform': [/*win32,*/'darwin'],
    'version': '1.2.1'
  };

  packager(options, function done_callback(err, appPaths) {
    console.log(err, appPaths);
  });
});

gulp.task('unit-tests', function () {

  // gulp expects tasks to return a stream, so we create one here.
  var bundledStream = through();

  bundledStream
    // turns the output bundle stream into a stream containing
    // the normal attributes gulp plugins expect.
    .pipe(source('stores-test.js'))
    // the rest of the gulp task, as you would normally write it.
    .pipe(buffer())
    .pipe(gulp.dest('./app/test/scripts/build/'))
    .pipe(mocha({
      bail: false,
      reporter: 'doc'
    }));

  // "globby" replaces the normal "gulp.src" as Browserify
  // creates it's own readable stream.
  globby(['./app/test/scripts/specs/*.js'], function(err, entries) {
    // ensure any errors from globby are handled
    if (err) {
      bundledStream.emit('error', err);
      return;
    }

    // create the Browserify instance and pipe the Browserify stream into the stream we created earlier
    // this starts our gulp pipeline.
    browserify({
      entries: entries
    })
    .ignore('browserify-fs')
    .bundle()
    .pipe(bundledStream);
  });

  // finally, we return the stream, so gulp knows when this task is done.
  return bundledStream;
});

// Build Production Files, the Default Task
gulp.task('default', ['clean'], function (cb) {
  runSequence(
    'browserify',
    ['copy', 'styles'],
    'elements',
    ['jshint', 'images', 'fonts', 'html', /*'unit-tests'*/],
    //'vulcanize',
    cb);
    // Note: add , 'precache' , after 'vulcanize', if your are going to use Service Worker
});

// Load tasks for web-component-tester
// Adds tasks for `gulp test:local` and `gulp test:remote`
//require('web-component-tester').gulp.init(gulp);

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<|endoftext|>