<commit_before>import {CompositeLayer, _flatten as flatten} from '@deck.gl/core';
import {GeoJsonLayer} from '@deck.gl/layers';
import {load} from '@loaders.gl/core';

import Tileset2D, {STRATEGY_DEFAULT} from './tileset-2d';
import {urlType, getURLFromTemplate} from './utils';

const defaultProps = {
  data: [],
  dataComparator: urlType.equals,
  renderSubLayers: {type: 'function', value: props => new GeoJsonLayer(props), compare: false},
  getTileData: {type: 'function', optional: true, value: null, compare: false},
  // TODO - change to onViewportLoad to align with Tile3DLayer
  onViewportLoad: {type: 'function', optional: true, value: null, compare: false},
  onTileLoad: {type: 'function', value: tile => {}, compare: false},
  onTileUnload: {type: 'function', value: tile => {}, compare: false},
  // eslint-disable-next-line
  onTileError: {type: 'function', value: err => console.error(err), compare: false},
  extent: {type: 'array', optional: true, value: null, compare: true},
  tileSize: 512,
  maxZoom: null,
  minZoom: 0,
  maxCacheSize: null,
  maxCacheByteSize: null,
  refinementStrategy: STRATEGY_DEFAULT,
  zRange: null,
  // Use load directly so we don't use ResourceManager
  fetch: {
    type: 'function',
    value: (url, {layer, signal}) => {
      const loadOptions = {signal, ...(layer.getLoadOptions() || {})};

      return load(url, loadOptions);
    },
    compare: false
  },
  maxRequests: 6
};

export default class TileLayer extends CompositeLayer {
  initializeState() {
    this.state = {
      tileset: null,
      isLoaded: false
    };
  }

  finalizeState() {
    const {tileset} = this.state;
    if (tileset) {
      tileset.finalize();
    }
  }

  get isLoaded() {
    const {tileset} = this.state;
    return tileset.selectedTiles.every(
      tile => tile.layers && tile.layers.every(layer => layer.isLoaded)
    );
  }

  shouldUpdateState({changeFlags}) {
    return changeFlags.somethingChanged;
  }

  updateState({props, oldProps, context, changeFlags}) {
    let {tileset} = this.state;
    const createTileCache =
      !tileset ||
      changeFlags.dataChanged ||
      (changeFlags.updateTriggersChanged &&
        (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getTileData));

    if (createTileCache) {
      if (tileset) {
        tileset.finalize();
      }
      const maxZoom = Number.isFinite(this.state.maxZoom) ? this.state.maxZoom : props.maxZoom;
      const minZoom = Number.isFinite(this.state.minZoom) ? this.state.minZoom : props.minZoom;
      const {
        tileSize,
        maxCacheSize,
        maxCacheByteSize,
        refinementStrategy,
        extent,
        maxRequests
      } = props;
      tileset = new Tileset2D({
        getTileData: this.getTileData.bind(this),
        maxCacheSize,
        maxCacheByteSize,
        maxZoom,
        minZoom,
        tileSize,
        refinementStrategy,
        extent,
        onTileLoad: this._onTileLoad.bind(this),
        onTileError: this._onTileError.bind(this),
        onTileUnload: this._onTileUnload.bind(this),
        maxRequests
      });
      this.setState({tileset});
    } else if (changeFlags.propsChanged || changeFlags.updateTriggersChanged) {
      tileset.setOptions(props);
      // if any props changed, delete the cached layers
      this.state.tileset.tiles.forEach(tile => {
        tile.layers = null;
      });
    }

    this._updateTileset();
  }

  _updateTileset() {
    const {tileset} = this.state;
    const {zRange, modelMatrix} = this.props;
    const frameNumber = tileset.update(this.context.viewport, {zRange, modelMatrix});
    const {isLoaded} = tileset;

    const loadingStateChanged = this.state.isLoaded !== isLoaded;
    const tilesetChanged = this.state.frameNumber !== frameNumber;

    if (isLoaded && (loadingStateChanged || tilesetChanged)) {
      this._onViewportLoad();
    }

    if (tilesetChanged) {
      // Save the tileset frame number - trigger a rerender
      this.setState({frameNumber});
    }
    // Save the loaded state - should not trigger a rerender
    this.state.isLoaded = isLoaded;
  }

  _onViewportLoad() {
    const {tileset} = this.state;
    const {onViewportLoad} = this.props;

    if (onViewportLoad) {
      onViewportLoad(tileset.selectedTiles);
    }
  }

  _onTileLoad(tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileLoad(tile);

    if (tile.isVisible) {
      this.setNeedsUpdate();
    }
  }

  _onTileError(error, tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileError(error);
    // errorred tiles should not block rendering, are considered "loaded" with empty data
    layer._updateTileset();

    if (tile.isVisible) {
      this.setNeedsUpdate();
    }
  }

  _onTileUnload(tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileUnload(tile);
  }

  // Methods for subclass to override

  getTileData(tile) {
    const {data} = this.props;
    const {getTileData, fetch} = this.getCurrentLayer().props;
    const {signal} = tile;

    tile.url = getURLFromTemplate(data, tile);

    if (getTileData) {
      return getTileData(tile);
    }
    if (tile.url) {
      return fetch(tile.url, {layer: this, signal});
    }
    return null;
  }

  renderSubLayers(props) {
    return this.props.renderSubLayers(props);
  }

  getHighlightedObjectIndex() {
    return -1;
  }

  getPickingInfo({info, sourceLayer}) {
    info.tile = sourceLayer.props.tile;
    return info;
  }

  _updateAutoHighlight(info) {
    if (info.sourceLayer) {
      info.sourceLayer.updateAutoHighlight(info);
    }
  }

  renderLayers() {
    const {visible} = this.props;
    return this.state.tileset.tiles.map(tile => {
      // For a tile to be visible:
      // - parent layer must be visible
      // - tile must be visible in the current viewport
      const isVisible = visible && tile.isVisible;
      const highlightedObjectIndex = this.getHighlightedObjectIndex(tile);
      // cache the rendered layer in the tile
      if (!tile.isLoaded) {
        // no op
      } else if (!tile.layers) {
        const layers = this.renderSubLayers(
          Object.assign({}, this.props, {
            id: `${this.id}-${tile.x}-${tile.y}-${tile.z}`,
            data: tile.data,
            visible: isVisible,
            _offset: 0,
            tile,
            highlightedObjectIndex
          })
        );
        tile.layers = flatten(layers, Boolean);
      } else if (
        tile.layers[0] &&
        (tile.layers[0].props.visible !== isVisible ||
          tile.layers[0].props.highlightedObjectIndex !== highlightedObjectIndex)
      ) {
        tile.layers = tile.layers.map(layer =>
          layer.clone({visible: isVisible, highlightedObjectIndex})
        );
      }
      return tile.layers;
    });
  }
}

TileLayer.layerName = 'TileLayer';
TileLayer.defaultProps = defaultProps;
<commit_msg>Fix TileLayer fetch options (#5521)<commit_after>import {CompositeLayer, _flatten as flatten} from '@deck.gl/core';
import {GeoJsonLayer} from '@deck.gl/layers';
import {load} from '@loaders.gl/core';

import Tileset2D, {STRATEGY_DEFAULT} from './tileset-2d';
import {urlType, getURLFromTemplate} from './utils';

const defaultProps = {
  data: [],
  dataComparator: urlType.equals,
  renderSubLayers: {type: 'function', value: props => new GeoJsonLayer(props), compare: false},
  getTileData: {type: 'function', optional: true, value: null, compare: false},
  // TODO - change to onViewportLoad to align with Tile3DLayer
  onViewportLoad: {type: 'function', optional: true, value: null, compare: false},
  onTileLoad: {type: 'function', value: tile => {}, compare: false},
  onTileUnload: {type: 'function', value: tile => {}, compare: false},
  // eslint-disable-next-line
  onTileError: {type: 'function', value: err => console.error(err), compare: false},
  extent: {type: 'array', optional: true, value: null, compare: true},
  tileSize: 512,
  maxZoom: null,
  minZoom: 0,
  maxCacheSize: null,
  maxCacheByteSize: null,
  refinementStrategy: STRATEGY_DEFAULT,
  zRange: null,
  // Use load directly so we don't use ResourceManager
  fetch: {
    type: 'function',
    value: (url, {layer, signal}) => {
      const loadOptions = {...layer.getLoadOptions()};
      loadOptions.fetch = {
        ...loadOptions.fetch,
        signal
      };

      return load(url, loadOptions);
    },
    compare: false
  },
  maxRequests: 6
};

export default class TileLayer extends CompositeLayer {
  initializeState() {
    this.state = {
      tileset: null,
      isLoaded: false
    };
  }

  finalizeState() {
    const {tileset} = this.state;
    if (tileset) {
      tileset.finalize();
    }
  }

  get isLoaded() {
    const {tileset} = this.state;
    return tileset.selectedTiles.every(
      tile => tile.layers && tile.layers.every(layer => layer.isLoaded)
    );
  }

  shouldUpdateState({changeFlags}) {
    return changeFlags.somethingChanged;
  }

  updateState({props, oldProps, context, changeFlags}) {
    let {tileset} = this.state;
    const createTileCache =
      !tileset ||
      changeFlags.dataChanged ||
      (changeFlags.updateTriggersChanged &&
        (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getTileData));

    if (createTileCache) {
      if (tileset) {
        tileset.finalize();
      }
      const maxZoom = Number.isFinite(this.state.maxZoom) ? this.state.maxZoom : props.maxZoom;
      const minZoom = Number.isFinite(this.state.minZoom) ? this.state.minZoom : props.minZoom;
      const {
        tileSize,
        maxCacheSize,
        maxCacheByteSize,
        refinementStrategy,
        extent,
        maxRequests
      } = props;
      tileset = new Tileset2D({
        getTileData: this.getTileData.bind(this),
        maxCacheSize,
        maxCacheByteSize,
        maxZoom,
        minZoom,
        tileSize,
        refinementStrategy,
        extent,
        onTileLoad: this._onTileLoad.bind(this),
        onTileError: this._onTileError.bind(this),
        onTileUnload: this._onTileUnload.bind(this),
        maxRequests
      });
      this.setState({tileset});
    } else if (changeFlags.propsChanged || changeFlags.updateTriggersChanged) {
      tileset.setOptions(props);
      // if any props changed, delete the cached layers
      this.state.tileset.tiles.forEach(tile => {
        tile.layers = null;
      });
    }

    this._updateTileset();
  }

  _updateTileset() {
    const {tileset} = this.state;
    const {zRange, modelMatrix} = this.props;
    const frameNumber = tileset.update(this.context.viewport, {zRange, modelMatrix});
    const {isLoaded} = tileset;

    const loadingStateChanged = this.state.isLoaded !== isLoaded;
    const tilesetChanged = this.state.frameNumber !== frameNumber;

    if (isLoaded && (loadingStateChanged || tilesetChanged)) {
      this._onViewportLoad();
    }

    if (tilesetChanged) {
      // Save the tileset frame number - trigger a rerender
      this.setState({frameNumber});
    }
    // Save the loaded state - should not trigger a rerender
    this.state.isLoaded = isLoaded;
  }

  _onViewportLoad() {
    const {tileset} = this.state;
    const {onViewportLoad} = this.props;

    if (onViewportLoad) {
      onViewportLoad(tileset.selectedTiles);
    }
  }

  _onTileLoad(tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileLoad(tile);

    if (tile.isVisible) {
      this.setNeedsUpdate();
    }
  }

  _onTileError(error, tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileError(error);
    // errorred tiles should not block rendering, are considered "loaded" with empty data
    layer._updateTileset();

    if (tile.isVisible) {
      this.setNeedsUpdate();
    }
  }

  _onTileUnload(tile) {
    const layer = this.getCurrentLayer();
    layer.props.onTileUnload(tile);
  }

  // Methods for subclass to override

  getTileData(tile) {
    const {data} = this.props;
    const {getTileData, fetch} = this.getCurrentLayer().props;
    const {signal} = tile;

    tile.url = getURLFromTemplate(data, tile);

    if (getTileData) {
      return getTileData(tile);
    }
    if (tile.url) {
      return fetch(tile.url, {layer: this, signal});
    }
    return null;
  }

  renderSubLayers(props) {
    return this.props.renderSubLayers(props);
  }

  getHighlightedObjectIndex() {
    return -1;
  }

  getPickingInfo({info, sourceLayer}) {
    info.tile = sourceLayer.props.tile;
    return info;
  }

  _updateAutoHighlight(info) {
    if (info.sourceLayer) {
      info.sourceLayer.updateAutoHighlight(info);
    }
  }

  renderLayers() {
    const {visible} = this.props;
    return this.state.tileset.tiles.map(tile => {
      // For a tile to be visible:
      // - parent layer must be visible
      // - tile must be visible in the current viewport
      const isVisible = visible && tile.isVisible;
      const highlightedObjectIndex = this.getHighlightedObjectIndex(tile);
      // cache the rendered layer in the tile
      if (!tile.isLoaded) {
        // no op
      } else if (!tile.layers) {
        const layers = this.renderSubLayers(
          Object.assign({}, this.props, {
            id: `${this.id}-${tile.x}-${tile.y}-${tile.z}`,
            data: tile.data,
            visible: isVisible,
            _offset: 0,
            tile,
            highlightedObjectIndex
          })
        );
        tile.layers = flatten(layers, Boolean);
      } else if (
        tile.layers[0] &&
        (tile.layers[0].props.visible !== isVisible ||
          tile.layers[0].props.highlightedObjectIndex !== highlightedObjectIndex)
      ) {
        tile.layers = tile.layers.map(layer =>
          layer.clone({visible: isVisible, highlightedObjectIndex})
        );
      }
      return tile.layers;
    });
  }
}

TileLayer.layerName = 'TileLayer';
TileLayer.defaultProps = defaultProps;
<|endoftext|>


<commit_before>var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var gutil = require('gulp-util');
// Temporary solution until gulp 4
// https://github.com/gulpjs/gulp/issues/355
var runSequence = require('run-sequence');
var Server = require('karma').Server;
var argv = require('yargs').argv;
var gulpif = require('gulp-if');
var es6Conf = require('./esixstarter-conf.json');
var dirs = es6Conf.dirs;
var banner = '/* ' + es6Conf.name + ' v' + es6Conf.version +
            ' | ' + es6Conf.author + ' */\n\n';

// -------- HELPER TASKS

gulp.task('lint:js', function () {
    return gulp.src([
        'gulpfile.js',
        dirs.src + '/js/*.js',
        dirs.test + '/*.spec.js'
    ]).pipe(plugins.plumber())
      .pipe(plugins.jshint())
      .pipe(plugins.jshint.reporter('jshint-stylish'))
      .pipe(plugins.jshint.reporter('fail'));
});

gulp.task('clean', function (done) {
    require('del')([
        dirs.dist
    ]).then(function () {
        done();
    });
});

gulp.task('scripts', function (done) {
     var b = browserify({
       entries: [dirs.src + '/js/main.js'],
       debug: true,
       transform: [["babelify", { "presets": ["es2015"] }]]
     });

     return b.bundle()
        .pipe(source('main.min.js'))
        .pipe(buffer())
        // sourcemaps - currently not working
        // .pipe(gulpif(!argv.production,plugins.sourcemaps.init({loadMaps: true})))
        .pipe(gulpif(!argv.production(plugins.uglify({mangle:true})))
          .on('error', gutil.log)
        // .pipe(gulpif(!argv.production,plugins.sourcemaps.write('./')))
        .pipe(plugins.header(banner))
        .pipe(gulp.dest(dirs.dist + '/js'))
        .pipe(plugins.connect.reload());
});

gulp.task('styles', function () {
  return gulp.src([
        dirs.src + '/less/*.less'
  ]).pipe(plugins.header(banner))
    .pipe(plugins.plumber())
    .pipe(plugins.less())
    .pipe(plugins.autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
    .pipe(gulpif(argv.production,plugins.cssnano()))
    .pipe(plugins.concat('main.min.css'))
    .pipe(gulp.dest(dirs.dist + '/css'))
    .pipe(plugins.connect.reload());
});

gulp.task('source', function () {
    return gulp.src([
        dirs.src + '/**/*',
        '!' + dirs.src + '/less/*.less',
        '!' + dirs.src + '/less',
        '!' + dirs.src + '/js/*.js'
    ], {
        // Include hidden files by default
        dot: true
    }).pipe(gulp.dest(dirs.dist));
      // .pipe(plugins.connect.reload());
});

gulp.task('copy', ['scripts','styles','source']);

// -------- TEST TASK

gulp.task('test', function (done) {
   new Server({
     configFile: __dirname + '/karma.conf.js',
     singleRun: true
   },done).start();
 });

// -------- MAIN TASKS

gulp.task('build', function (done) {
    runSequence(
        ['clean','test','lint:js'],
        'copy',
    done);
});

gulp.task('dev',['copy','connect'], function () {
   // Watching files
   gulp.watch(
        [dirs.src + '/js/*.js',dirs.test + '/*.js',
          dirs.src + '/less/*.less',dirs.src + '/*.html'],
        ['lint:js','scripts','styles','source']
    );

    // Starting Karma for test execution
    new Server({
      configFile: __dirname + '/karma.conf.js',
      singleRun: false,
      background: true
    }).start();
});

// Web Server
gulp.task('connect', function() {
  plugins.connect.server({
    root: [dirs.dist],
    livereload: true
  });
});

// Starting a web server and karma for tdd.
gulp.task('default', ['dev']);
<commit_msg>Fixed the scripts task<commit_after>var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var gutil = require('gulp-util');
// Temporary solution until gulp 4
// https://github.com/gulpjs/gulp/issues/355
var runSequence = require('run-sequence');
var Server = require('karma').Server;
var argv = require('yargs').argv;
var gulpif = require('gulp-if');
var es6Conf = require('./esixstarter-conf.json');
var dirs = es6Conf.dirs;
var banner = '/* ' + es6Conf.name + ' v' + es6Conf.version +
            ' | ' + es6Conf.author + ' */\n\n';

// -------- HELPER TASKS

gulp.task('lint:js', function () {
    return gulp.src([
        'gulpfile.js',
        dirs.src + '/js/*.js',
        dirs.test + '/*.spec.js'
    ]).pipe(plugins.plumber())
      .pipe(plugins.jshint())
      .pipe(plugins.jshint.reporter('jshint-stylish'))
      .pipe(plugins.jshint.reporter('fail'));
});

gulp.task('clean', function (done) {
    require('del')([
        dirs.dist
    ]).then(function () {
        done();
    });
});

gulp.task('scripts', function (done) {
     var b = browserify({
       entries: [dirs.src + '/js/main.js'],
       debug: true,
       transform: [["babelify", { "presets": ["es2015"] }]]
     });

     return b.bundle()
        .pipe(source('main.min.js'))
        .pipe(buffer())
        // sourcemaps - currently not working
        // .pipe(gulpif(!argv.production,plugins.sourcemaps.init({loadMaps: true})))
        .pipe(gulpif(!argv.production,plugins.uglify({mangle:true})))
          .on('error', gutil.log)
        // .pipe(gulpif(!argv.production,plugins.sourcemaps.write('./')))
        .pipe(plugins.header(banner))
        .pipe(gulp.dest(dirs.dist + '/js'))
        .pipe(plugins.connect.reload());
});

gulp.task('styles', function () {
  return gulp.src([
        dirs.src + '/less/*.less'
  ]).pipe(plugins.header(banner))
    .pipe(plugins.plumber())
    .pipe(plugins.less())
    .pipe(plugins.autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
    .pipe(gulpif(argv.production,plugins.cssnano()))
    .pipe(plugins.concat('main.min.css'))
    .pipe(gulp.dest(dirs.dist + '/css'))
    .pipe(plugins.connect.reload());
});

gulp.task('source', function () {
    return gulp.src([
        dirs.src + '/**/*',
        '!' + dirs.src + '/less/*.less',
        '!' + dirs.src + '/less',
        '!' + dirs.src + '/js/*.js'
    ], {
        // Include hidden files by default
        dot: true
    }).pipe(gulp.dest(dirs.dist));
      // .pipe(plugins.connect.reload());
});

gulp.task('copy', ['scripts','styles','source']);

// -------- TEST TASK

gulp.task('test', function (done) {
   new Server({
     configFile: __dirname + '/karma.conf.js',
     singleRun: true
   },done).start();
 });

// -------- MAIN TASKS

gulp.task('build', function (done) {
    runSequence(
        ['clean','test','lint:js'],
        'copy',
    done);
});

gulp.task('dev',['copy','connect'], function () {
   // Watching files
   gulp.watch(
        [dirs.src + '/js/*.js',dirs.test + '/*.js',
          dirs.src + '/less/*.less',dirs.src + '/*.html'],
        ['lint:js','scripts','styles','source']
    );

    // Starting Karma for test execution
    new Server({
      configFile: __dirname + '/karma.conf.js',
      singleRun: false,
      background: true
    }).start();
});

// Web Server
gulp.task('connect', function() {
  plugins.connect.server({
    root: [dirs.dist],
    livereload: true
  });
});

// Starting a web server and karma for tdd.
gulp.task('default', ['dev']);
<|endoftext|>


<commit_before>const gulp = require('gulp');
const loadPlugins = require('gulp-load-plugins');
const del = require('del');
const glob = require('glob');
const path = require('path');
const isparta = require('isparta');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');

const Instrumenter = isparta.Instrumenter;
const mochaGlobals = require('./test/setup/.globals');
const manifest = require('./package.json');

// Load all of our Gulp plugins
const $ = loadPlugins();

// Gather the library data from `package.json`
const config = manifest.babelBoilerplateOptions;
const mainFile = manifest.main;
const destinationFolder = path.dirname(mainFile);
const exportFileName = path.basename(mainFile, path.extname(mainFile));

function cleanDist(done) {
  del([destinationFolder]).then(() => done());
}

function cleanTmp(done) {
  del(['tmp']).then(() => done());
}

// Lint a set of files
function lint(files) {
  return gulp.src(files)
    .pipe($.eslint())
    .pipe($.eslint.format())
    .pipe($.eslint.failAfterError());
}

function lintSrc() {
  return lint('src/**/*.js');
}

function lintTest() {
  return lint('test/**/*.js');
}

function lintGulpfile() {
  return lint('gulpfile.js');
}

function build() {
  return gulp.src(path.join('src', config.entryFileName))
    .pipe(webpackStream({
      output: {
        filename: `${exportFileName}.js`,
        libraryTarget: 'umd',
        library: config.mainVarName
      },
      // Add your own externals here. For instance,
      // {
      //   jquery: true
      // }
      // would externalize the `jquery` module.
      externals: {},
      module: {
        loaders: [
          {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}
        ]
      },
      devtool: 'source-map'
    }))
    .pipe(gulp.dest(destinationFolder))
    .pipe($.filter(['**', '!**/*.js.map']))
    .pipe($.rename(`${exportFileName}.min.js`))
    .pipe($.sourcemaps.init({loadMaps: true}))
    .pipe($.uglify())
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest(destinationFolder));
}

function _mocha() {
  return gulp.src(['test/setup/node.js', 'test/unit/**/*.js'], {read: false})
    .pipe($.mocha({
      reporter: 'dot',
      globals: Object.keys(mochaGlobals.globals),
      ignoreLeaks: false
    }));
}

function _registerBabel() {
  require('babel-register');
}

function test() {
  _registerBabel();
  return _mocha();
}

function coverage(done) {
  _registerBabel();
  gulp.src(['src/**/*.js'])
    .pipe($.istanbul({
      instrumenter: Instrumenter,
      includeUntested: true
    }))
    .pipe($.istanbul.hookRequire())
    .on('finish', () => {
      return test()
        .pipe($.istanbul.writeReports())
        .on('end', done);
    });
}

const watchFiles = ['src/**/*', 'test/**/*', 'package.json', '**/.eslintrc'];

// Run the headless unit tests as you make changes.
function watch() {
  gulp.watch(watchFiles, ['test']);
}

function testBrowser() {
  // Our testing bundle is made up of our unit tests, which
  // should individually load up pieces of our application.
  // We also include the browser setup file.
  const testFiles = glob.sync('./test/unit/**/*.js');
  const allFiles = ['./test/setup/browser.js'].concat(testFiles);

  // Lets us differentiate between the first build and subsequent builds
  var firstBuild = true;

  // This empty stream might seem like a hack, but we need to specify all of our files through
  // the `entry` option of webpack. Otherwise, it ignores whatever file(s) are placed in here.
  return gulp.src('')
    .pipe($.plumber())
    .pipe(webpackStream({
      watch: true,
      entry: allFiles,
      output: {
        filename: '__spec-build.js'
      },
      // Externals isn't necessary here since these are for tests.
      module: {
        loaders: [
          // This is what allows us to author in future JavaScript
          {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
          // This allows the test setup scripts to load `package.json`
          {test: /\.json$/, exclude: /node_modules/, loader: 'json-loader'}
        ]
      },
      plugins: [
        // By default, webpack does `n=>n` compilation with entry files. This concatenates
        // them into a single chunk.
        new webpack.optimize.LimitChunkCountPlugin({maxChunks: 1})
      ],
      devtool: 'inline-source-map'
    }, null, () => {
      if (firstBuild) {
        $.livereload.listen({port: 35729, host: 'localhost', start: true});
        gulp.watch(watchFiles, ['lint']);
      } else {
        $.livereload.reload('./tmp/__spec-build.js');
      }
      firstBuild = false;
    }))
    .pipe(gulp.dest('./tmp'));
}

// Remove the built files
gulp.task('clean', cleanDist);

// Remove our temporary files
gulp.task('clean-tmp', cleanTmp);

// Lint our source code
gulp.task('lint-src', lintSrc);

// Lint our test code
gulp.task('lint-test', lintTest);

// Lint this file
gulp.task('lint-gulpfile', lintGulpfile);

// Lint everything
gulp.task('lint', ['lint-src', 'lint-test', 'lint-gulpfile']);

// Build two versions of the library
gulp.task('build', ['lint', 'clean'], build);

// Lint and run our tests
gulp.task('test', ['lint'], test);

// Set up coverage and run tests
gulp.task('coverage', ['lint'], coverage);

// Set up a livereload environment for our spec runner `test/runner.html`
gulp.task('test-browser', ['lint', 'clean-tmp'], testBrowser);

// Run the headless unit tests as you make changes.
gulp.task('watch', watch);

// An alias of test
gulp.task('default', ['test']);
<commit_msg>Rearrange to put test functions together<commit_after>const gulp = require('gulp');
const loadPlugins = require('gulp-load-plugins');
const del = require('del');
const glob = require('glob');
const path = require('path');
const isparta = require('isparta');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');

const Instrumenter = isparta.Instrumenter;
const mochaGlobals = require('./test/setup/.globals');
const manifest = require('./package.json');

// Load all of our Gulp plugins
const $ = loadPlugins();

// Gather the library data from `package.json`
const config = manifest.babelBoilerplateOptions;
const mainFile = manifest.main;
const destinationFolder = path.dirname(mainFile);
const exportFileName = path.basename(mainFile, path.extname(mainFile));

function cleanDist(done) {
  del([destinationFolder]).then(() => done());
}

function cleanTmp(done) {
  del(['tmp']).then(() => done());
}

// Lint a set of files
function lint(files) {
  return gulp.src(files)
    .pipe($.eslint())
    .pipe($.eslint.format())
    .pipe($.eslint.failAfterError());
}

function lintSrc() {
  return lint('src/**/*.js');
}

function lintTest() {
  return lint('test/**/*.js');
}

function lintGulpfile() {
  return lint('gulpfile.js');
}

function build() {
  return gulp.src(path.join('src', config.entryFileName))
    .pipe(webpackStream({
      output: {
        filename: `${exportFileName}.js`,
        libraryTarget: 'umd',
        library: config.mainVarName
      },
      // Add your own externals here. For instance,
      // {
      //   jquery: true
      // }
      // would externalize the `jquery` module.
      externals: {},
      module: {
        loaders: [
          {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}
        ]
      },
      devtool: 'source-map'
    }))
    .pipe(gulp.dest(destinationFolder))
    .pipe($.filter(['**', '!**/*.js.map']))
    .pipe($.rename(`${exportFileName}.min.js`))
    .pipe($.sourcemaps.init({loadMaps: true}))
    .pipe($.uglify())
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest(destinationFolder));
}

function _mocha() {
  return gulp.src(['test/setup/node.js', 'test/unit/**/*.js'], {read: false})
    .pipe($.mocha({
      reporter: 'dot',
      globals: Object.keys(mochaGlobals.globals),
      ignoreLeaks: false
    }));
}

function _registerBabel() {
  require('babel-register');
}

function test() {
  _registerBabel();
  return _mocha();
}

function testBrowser() {
  // Our testing bundle is made up of our unit tests, which
  // should individually load up pieces of our application.
  // We also include the browser setup file.
  const testFiles = glob.sync('./test/unit/**/*.js');
  const allFiles = ['./test/setup/browser.js'].concat(testFiles);

  // Lets us differentiate between the first build and subsequent builds
  var firstBuild = true;

  // This empty stream might seem like a hack, but we need to specify all of our files through
  // the `entry` option of webpack. Otherwise, it ignores whatever file(s) are placed in here.
  return gulp.src('')
    .pipe($.plumber())
    .pipe(webpackStream({
      watch: true,
      entry: allFiles,
      output: {
        filename: '__spec-build.js'
      },
      // Externals isn't necessary here since these are for tests.
      module: {
        loaders: [
          // This is what allows us to author in future JavaScript
          {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
          // This allows the test setup scripts to load `package.json`
          {test: /\.json$/, exclude: /node_modules/, loader: 'json-loader'}
        ]
      },
      plugins: [
        // By default, webpack does `n=>n` compilation with entry files. This concatenates
        // them into a single chunk.
        new webpack.optimize.LimitChunkCountPlugin({maxChunks: 1})
      ],
      devtool: 'inline-source-map'
    }, null, () => {
      if (firstBuild) {
        $.livereload.listen({port: 35729, host: 'localhost', start: true});
        gulp.watch(watchFiles, ['lint']);
      } else {
        $.livereload.reload('./tmp/__spec-build.js');
      }
      firstBuild = false;
    }))
    .pipe(gulp.dest('./tmp'));
}

function coverage(done) {
  _registerBabel();
  gulp.src(['src/**/*.js'])
    .pipe($.istanbul({
      instrumenter: Instrumenter,
      includeUntested: true
    }))
    .pipe($.istanbul.hookRequire())
    .on('finish', () => {
      return test()
        .pipe($.istanbul.writeReports())
        .on('end', done);
    });
}

const watchFiles = ['src/**/*', 'test/**/*', 'package.json', '**/.eslintrc'];

// Run the headless unit tests as you make changes.
function watch() {
  gulp.watch(watchFiles, ['test']);
}

// Remove the built files
gulp.task('clean', cleanDist);

// Remove our temporary files
gulp.task('clean-tmp', cleanTmp);

// Lint our source code
gulp.task('lint-src', lintSrc);

// Lint our test code
gulp.task('lint-test', lintTest);

// Lint this file
gulp.task('lint-gulpfile', lintGulpfile);

// Lint everything
gulp.task('lint', ['lint-src', 'lint-test', 'lint-gulpfile']);

// Build two versions of the library
gulp.task('build', ['lint', 'clean'], build);

// Lint and run our tests
gulp.task('test', ['lint'], test);

// Set up coverage and run tests
gulp.task('coverage', ['lint'], coverage);

// Set up a livereload environment for our spec runner `test/runner.html`
gulp.task('test-browser', ['lint', 'clean-tmp'], testBrowser);

// Run the headless unit tests as you make changes.
gulp.task('watch', watch);

// An alias of test
gulp.task('default', ['test']);
<|endoftext|>


<commit_before>(function() {
  'use strict';

  function SequoiaTree($log) {

    var _checkNodeStructure, _exists, _contains, _buildBreadCrumbs, _buildPath, _selected, _createNodeWithFullPathAsTitle;

    var SequoiaTree = function(tree, template) {
      var nodeTemplate = {
        id: '_id',
        nodes: 'nodes',
        title: 'title'
      };

      this.template = template || nodeTemplate;
      this.tree = _checkNodeStructure(_.isArray(tree) ? tree[0] : [], this.template) ? tree : [];
    };

    _checkNodeStructure = function(node, template) {
      var keys = _.values(template);
      for(var i=0;i<keys.length;i++) {
        if (!_.has(node, keys[i])) {
          $log.warn('The node structure is not valid!');
          return false;
        }
      }

      return true;
    };

    _exists = function (nodes, key, value, template) {
      if (_.isArray(nodes)) {
        return _.some(nodes, function(node){
          return node[key] === value ? true : _exists(node[template.nodes], key, value, template);
        });
      } else {
        return false;
      }
    };

    _contains = function (nodes, key, value, results, template) {
      if (_.isArray(nodes)) {
        for(var i=0;i<nodes.length;i++) {
          if(nodes[i][key].toLowerCase().indexOf(value.toLowerCase()) > -1) {
            results.push(nodes[i]);
          }
          _contains(nodes[i][template.nodes], key, value, results, template);
        }
      }

      return results;
    };

    _buildBreadCrumbs = function(id, nodes, breadcrumbs, template) {
      nodes = nodes || [];
      var root = {};
      root[template.title] = 'Root';
      breadcrumbs = !breadcrumbs.length ? [root] : breadcrumbs;

      for(var i=0;i<nodes.length;i++) {
        if(nodes[i][template.id] === id || _exists(nodes[i][template.nodes], template.id, id, template)) {
          breadcrumbs.push(nodes[i]);
        }
        _buildBreadCrumbs(id, nodes[i][template.nodes], breadcrumbs, template);
      }

      return breadcrumbs;
    };

    _buildPath = function(node, nodes, path, template) {
      nodes = nodes || [];

      for(var i=0;i<nodes.length;i++) {
        if(nodes[i][template.id] === node[template.id] || _exists(nodes[i][template.nodes], template.id, node[template.id], template)) {
          path += path.length ? ' > ' : '';
          path += _.trunc(nodes[i][template.title], 20);
        }
        path = _buildPath(node, nodes[i][template.nodes], path, template);
      }

      return path;
    };

    _selected = function(id, nodes, selected, template) {
      if(_.isArray(nodes)) {
        for(var i=0;i<nodes.length;i++) {
          if(nodes[i]._id === id) {
            selected.push(nodes[i]);
          }
          _selected(id, nodes[i][template.nodes], selected, template);
        }
      }

      return selected;
    };

    _createNodeWithFullPathAsTitle = function(node, tree, template) {
      var result = {};

      result[template.id] = node[template.id];
      result[template.title] = _buildPath(node, tree, '', template);

      return result;
    };

    SequoiaTree.prototype.setCurrentNodes = function(nodes) {
      this.nodes = !_.isArray(nodes) ? this.tree : nodes;
    };

    SequoiaTree.prototype.setNodesInPath = function(nodes) {
      this.nodesInPath = !_.isArray(nodes) ? this.tree : nodes;
    };

    SequoiaTree.prototype.getNodesInPath = function() {
      return _.isArray(this.nodesInPath) ? this.nodesInPath : this.tree;
    };

    SequoiaTree.prototype.isValidNode = function(node) {
      return _.isObject(node) && node[this.template.nodes];
    };

    SequoiaTree.prototype.breadcrumbs = function(id) {
      return _buildBreadCrumbs(id,this.tree,[], this.template);
    };

    SequoiaTree.prototype.find = function(key,value) {
      var results = [],
          found = _contains(this.tree, key, value, [], this.template);
      for(var i=0;i<found.length;i++) {
        results.push(_createNodeWithFullPathAsTitle(found[i], this.tree,this.template));
      }

      return results;
    };

    SequoiaTree.prototype.findSelected = function(ids) {
      var selected = [],
          results = [];

      if(_.isArray(ids)) {
        for(var i=0;i<ids.length;i++) {
          selected = _.union(selected, _selected(ids[i], this.tree, [], this.template));
        }

        for(var i=0;i<selected.length;i++) {
          results.push(_createNodeWithFullPathAsTitle(selected[i], this.tree,this.template));
        }
      } else {
        $log.warn('You must pass an array of IDs in order to find the selected nodes!');
      }

      return results;
    };

    return SequoiaTree;
  }

  SequoiaTree.$inject = ['$log'];

  angular.module('ngSequoia')
    .factory('SequoiaTree', SequoiaTree);

})();
<commit_msg>Change factory function definition name to avoid conflict with factory name<commit_after>(function() {
  'use strict';

  function SequoiaTreeFactory($log) {

    var _checkNodeStructure, _exists, _contains, _buildBreadCrumbs, _buildPath, _selected, _createNodeWithFullPathAsTitle;

    var SequoiaTree = function(tree, template) {
      var nodeTemplate = {
        id: '_id',
        nodes: 'nodes',
        title: 'title'
      };

      this.template = template || nodeTemplate;
      this.tree = _checkNodeStructure(_.isArray(tree) ? tree[0] : [], this.template) ? tree : [];
    };

    _checkNodeStructure = function(node, template) {
      var keys = _.values(template);
      for(var i=0;i<keys.length;i++) {
        if (!_.has(node, keys[i])) {
          $log.warn('The node structure is not valid!');
          return false;
        }
      }

      return true;
    };

    _exists = function (nodes, key, value, template) {
      if (_.isArray(nodes)) {
        return _.some(nodes, function(node){
          return node[key] === value ? true : _exists(node[template.nodes], key, value, template);
        });
      } else {
        return false;
      }
    };

    _contains = function (nodes, key, value, results, template) {
      if (_.isArray(nodes)) {
        for(var i=0;i<nodes.length;i++) {
          if(nodes[i][key].toLowerCase().indexOf(value.toLowerCase()) > -1) {
            results.push(nodes[i]);
          }
          _contains(nodes[i][template.nodes], key, value, results, template);
        }
      }

      return results;
    };

    _buildBreadCrumbs = function(id, nodes, breadcrumbs, template) {
      nodes = nodes || [];
      var root = {};
      root[template.title] = 'Root';
      breadcrumbs = !breadcrumbs.length ? [root] : breadcrumbs;

      for(var i=0;i<nodes.length;i++) {
        if(nodes[i][template.id] === id || _exists(nodes[i][template.nodes], template.id, id, template)) {
          breadcrumbs.push(nodes[i]);
        }
        _buildBreadCrumbs(id, nodes[i][template.nodes], breadcrumbs, template);
      }

      return breadcrumbs;
    };

    _buildPath = function(node, nodes, path, template) {
      nodes = nodes || [];

      for(var i=0;i<nodes.length;i++) {
        if(nodes[i][template.id] === node[template.id] || _exists(nodes[i][template.nodes], template.id, node[template.id], template)) {
          path += path.length ? ' > ' : '';
          path += _.trunc(nodes[i][template.title], 20);
        }
        path = _buildPath(node, nodes[i][template.nodes], path, template);
      }

      return path;
    };

    _selected = function(id, nodes, selected, template) {
      if(_.isArray(nodes)) {
        for(var i=0;i<nodes.length;i++) {
          if(nodes[i]._id === id) {
            selected.push(nodes[i]);
          }
          _selected(id, nodes[i][template.nodes], selected, template);
        }
      }

      return selected;
    };

    _createNodeWithFullPathAsTitle = function(node, tree, template) {
      var result = {};

      result[template.id] = node[template.id];
      result[template.title] = _buildPath(node, tree, '', template);

      return result;
    };

    SequoiaTree.prototype.setCurrentNodes = function(nodes) {
      this.nodes = !_.isArray(nodes) ? this.tree : nodes;
    };

    SequoiaTree.prototype.setNodesInPath = function(nodes) {
      this.nodesInPath = !_.isArray(nodes) ? this.tree : nodes;
    };

    SequoiaTree.prototype.getNodesInPath = function() {
      return _.isArray(this.nodesInPath) ? this.nodesInPath : this.tree;
    };

    SequoiaTree.prototype.isValidNode = function(node) {
      return _.isObject(node) && node[this.template.nodes];
    };

    SequoiaTree.prototype.breadcrumbs = function(id) {
      return _buildBreadCrumbs(id,this.tree,[], this.template);
    };

    SequoiaTree.prototype.find = function(key,value) {
      var results = [],
          found = _contains(this.tree, key, value, [], this.template);
      for(var i=0;i<found.length;i++) {
        results.push(_createNodeWithFullPathAsTitle(found[i], this.tree,this.template));
      }

      return results;
    };

    SequoiaTree.prototype.findSelected = function(ids) {
      var selected = [],
          results = [];

      if(_.isArray(ids)) {
        for(var i=0;i<ids.length;i++) {
          selected = _.union(selected, _selected(ids[i], this.tree, [], this.template));
        }

        for(var j=0;j<selected.length;j++) {
          results.push(_createNodeWithFullPathAsTitle(selected[j], this.tree,this.template));
        }
      } else {
        $log.warn('You must pass an array of IDs in order to find the selected nodes!');
      }

      return results;
    };

    return SequoiaTree;
  }

  SequoiaTreeFactory.$inject = ['$log'];

  angular.module('ngSequoia')
    .factory('SequoiaTree', SequoiaTreeFactory);

})();
<|endoftext|>


<commit_before>/*

//// How it works?

Three ways:

1. Expressions: tmpl('{ value }', data).
   Returns the result of evaluated expression as a raw object.

2. Templates: tmpl('Hi { name } { surname }', data).
   Returns a string with evaluated expressions.

3. Filters: tmpl('{ show: !done, highlight: active }', data).
   Returns a space separated list of trueish keys (mainly
   used for setting html classes), e.g. "show highlight".

// Template examples

tmpl('{ title || "Untitled" }', data)
tmpl('Results are { results ? "ready" : "loading" }', data)
tmpl('Today is { new Date() }', data)
tmpl('{ message.length > 140 && "Message is too long" }', data)
tmpl('This item got { Math.round(rating) } stars', data)
tmpl('
{ title }
{ body }', data)

// Falsy expressions in templates

In templates (as opposed to single expressions) all falsy values
except zero (undefined/null/false) will default to empty string:

tmpl('{ undefined } - { false } - { null } - { 0 }', {})
// will return: " - - - 0"

*/

var brackets = (function(orig, s, b) {
  return function(x) {

    // make sure we use the current setting
    s = riot.settings.brackets || orig
    if (b != s) b = s.split(' ')

    // if regexp given, rewrite it with current brackets (only if differ from default)
    // else, get brackets
    return x && x.test
      ? s == orig
        ? x : RegExp(x.source
                      .replace(/\{/g, b[0].replace(/(?=.)/g, '\\'))
                      .replace(/\}/g, b[1].replace(/(?=.)/g, '\\')),
                    x.global ? 'g' : '')
      : b[x]

  }
})('{ }')

var tmpl = (function() {

  var cache = {},
      re_vars = /(['"\/]).*?[^\\]\1|\.\w*|\w*:|\b(?:(?:new|typeof|in|instanceof) |(?:this|true|false|null|undefined)\b|function *\()|([a-z_]\w*)/gi
              // [ 1               ][ 2  ][ 3 ][ 4                                                                                ][ 5       ]
              // find variable names:
              // 1. skip quoted strings and regexps: "a b", 'a b', 'a \'b\'', /a b/
              // 2. skip object properties: .name
              // 3. skip object literals: name:
              // 4. skip javascript keywords
              // 5. match var name

  // build a template (or get it from cache), render with data
  return function(str, data) {
    return str && (cache[str] = cache[str] || tmpl(str))(data)
  }

  // create a template instance

  function tmpl(s, p) {

    // default template string to {}
    s = (s || (brackets(0) + brackets(1)))

      // temporarily convert \{ and \} to a non-character
      .replace(brackets(/\\{/), '\uFFF0')
      .replace(brackets(/\\}/), '\uFFF1')

    // split string to expression and non-expresion parts
    p = split(s, brackets(/{[\s\S]*?}/g))

    return new Function('d', 'return ' + (

      // is it a single expression or a template? i.e. {x} or {x}
      !p[0] && !p[2] && !p[3]

        // if expression, evaluate it
        ? expr(p[1])

        // if template, evaluate all expressions in it
        : '[' + p.map(function(s, i) {

            // is it an expression or a string (every second part is an expression)
          return i % 2

              // evaluate the expressions
              ? expr(s, true)

              // process string parts of the template:
              : '"' + s

                  // preserve new lines
                  .replace(/\n/g, '\\n')

                  // escape quotes
                  .replace(/"/g, '\\"')

                + '"'

        }).join(',') + '].join("")'
      )

      // bring escaped { and } back
      .replace(/\uFFF0/g, brackets(0))
      .replace(/\uFFF1/g, brackets(1))

    + ';')

  }

  // parse { ... } expression

  function expr(s, n) {
    s = s

      // convert new lines to spaces
      .replace(/\n/g, ' ')

      // trim whitespace, curly brackets, strip comments
      .replace(brackets(/^[{ ]+|[ }]+$|\/\*.+?\*\//g), '')

    // is it an object literal? i.e. { key : value }
    return /^\s*[\w- "']+ *:/.test(s)

      // if object literal, return trueish keys
      // e.g.: { show: isOpen(), done: item.done } -> "show done"
      ? '[' + s.replace(/\W*([\w- ]+)\W*:([^,]+)/g, function(_, k, v) {

        return v.replace(/[^&|=!><]+/g, wrap) + '?"' + k.trim() + '":"",'

      }) + '].join(" ").trim()'

      // if js expression, evaluate as javascript
      : wrap(s, n)

  }

  // execute js w/o breaking on errors or undefined vars

  function wrap(s, nonull) {
    s = s.trim()
    return !s ? '' : '(function(v){try{v='

        // prefix vars (name => data.name)
        + (s.replace(re_vars, function(s, _, v) { return v ? '(d.'+v+'===undefined?window.'+v+':d.'+v+')' : s })

          // break the expression if its empty (resulting in undefined value)
          || 'x')

      + '}finally{return '

        // default to empty string for falsy values except zero
        + (nonull === true ? '!v&&v!==0?"":v' : 'v')

      + '}}).call(d)'
  }

  // a substitute for str.split(re) for IE8
  // because IE8 doesn't support capturing parenthesis in it

  function split(s, re){
    var parts = [], last = 0
    s.replace(re, function(m, i){
      // push matched expression and part before it
      parts.push(s.slice(last, i), m)
      last = i + m.length
    })
    // push the remaining part
    return parts.concat(s.slice(last))
  }

})()<commit_msg>Thanks jshint!<commit_after>/*

//// How it works?

Three ways:

1. Expressions: tmpl('{ value }', data).
   Returns the result of evaluated expression as a raw object.

2. Templates: tmpl('Hi { name } { surname }', data).
   Returns a string with evaluated expressions.

3. Filters: tmpl('{ show: !done, highlight: active }', data).
   Returns a space separated list of trueish keys (mainly
   used for setting html classes), e.g. "show highlight".

// Template examples

tmpl('{ title || "Untitled" }', data)
tmpl('Results are { results ? "ready" : "loading" }', data)
tmpl('Today is { new Date() }', data)
tmpl('{ message.length > 140 && "Message is too long" }', data)
tmpl('This item got { Math.round(rating) } stars', data)
tmpl('
{ title }
{ body }', data)

// Falsy expressions in templates

In templates (as opposed to single expressions) all falsy values
except zero (undefined/null/false) will default to empty string:

tmpl('{ undefined } - { false } - { null } - { 0 }', {})
// will return: " - - - 0"

*/

var brackets = (function(orig, s, b) {
  return function(x) {

    // make sure we use the current setting
    s = riot.settings.brackets || orig
    if (b != s) b = s.split(' ')

    // if regexp given, rewrite it with current brackets (only if differ from default)
    // else, get brackets
    return x && x.test
      ? s == orig
        ? x : RegExp(x.source
                      .replace(/\{/g, b[0].replace(/(?=.)/g, '\\'))
                      .replace(/\}/g, b[1].replace(/(?=.)/g, '\\')),
                    x.global ? 'g' : '')
      : b[x]

  }
})('{ }')

var tmpl = (function() {

  var cache = {},
      re_vars = /(['"\/]).*?[^\\]\1|\.\w*|\w*:|\b(?:(?:new|typeof|in|instanceof) |(?:this|true|false|null|undefined)\b|function *\()|([a-z_]\w*)/gi
              // [ 1               ][ 2  ][ 3 ][ 4                                                                                ][ 5       ]
              // find variable names:
              // 1. skip quoted strings and regexps: "a b", 'a b', 'a \'b\'', /a b/
              // 2. skip object properties: .name
              // 3. skip object literals: name:
              // 4. skip javascript keywords
              // 5. match var name

  // build a template (or get it from cache), render with data
  return function(str, data) {
    return str && (cache[str] = cache[str] || tmpl(str))(data)
  }

  // create a template instance

  function tmpl(s, p) {

    // default template string to {}
    s = (s || (brackets(0) + brackets(1)))

      // temporarily convert \{ and \} to a non-character
      .replace(brackets(/\\{/), '\uFFF0')
      .replace(brackets(/\\}/), '\uFFF1')

    // split string to expression and non-expresion parts
    p = split(s, brackets(/{[\s\S]*?}/g))

    return new Function('d', 'return ' + (

      // is it a single expression or a template? i.e. {x} or {x}
      !p[0] && !p[2] && !p[3]

        // if expression, evaluate it
        ? expr(p[1])

        // if template, evaluate all expressions in it
        : '[' + p.map(function(s, i) {

            // is it an expression or a string (every second part is an expression)
          return i % 2

              // evaluate the expressions
              ? expr(s, true)

              // process string parts of the template:
              : '"' + s

                  // preserve new lines
                  .replace(/\n/g, '\\n')

                  // escape quotes
                  .replace(/"/g, '\\"')

                + '"'

        }).join(',') + '].join("")'
      )

      // bring escaped { and } back
      .replace(/\uFFF0/g, brackets(0))
      .replace(/\uFFF1/g, brackets(1))

    + ';')

  }

  // parse { ... } expression

  function expr(s, n) {
    s = s

      // convert new lines to spaces
      .replace(/\n/g, ' ')

      // trim whitespace, curly brackets, strip comments
      .replace(brackets(/^[{ ]+|[ }]+$|\/\*.+?\*\//g), '')

    // is it an object literal? i.e. { key : value }
    return /^\s*[\w- "']+ *:/.test(s)

      // if object literal, return trueish keys
      // e.g.: { show: isOpen(), done: item.done } -> "show done"
      ? '[' + s.replace(/\W*([\w- ]+)\W*:([^,]+)/g, function(_, k, v) {

        return v.replace(/[^&|=!><]+/g, wrap) + '?"' + k.trim() + '":"",'

      }) + '].join(" ").trim()'

      // if js expression, evaluate as javascript
      : wrap(s, n)

  }

  // execute js w/o breaking on errors or undefined vars

  function wrap(s, nonull) {
    s = s.trim()
    return !s ? '' : '(function(v){try{v='

        // prefix vars (name => data.name)
        + (s.replace(re_vars, function(s, _, v) { return v ? '(d.'+v+'===undefined?window.'+v+':d.'+v+')' : s })

          // break the expression if its empty (resulting in undefined value)
          || 'x')

      + '}finally{return '

        // default to empty string for falsy values except zero
        + (nonull === true ? '!v&&v!==0?"":v' : 'v')

      + '}}).call(d)'
  }

  // a substitute for str.split(re) for IE8
  // because IE8 doesn't support capturing parenthesis in it

  function split(s, re) {
    var parts = [], last = 0
    s.replace(re, function(m, i) {
      // push matched expression and part before it
      parts.push(s.slice(last, i), m)
      last = i + m.length
    })
    // push the remaining part
    return parts.concat(s.slice(last))
  }

})()<|endoftext|>


<commit_before>var gulp        = require('gulp');
var browserSync = require('browser-sync');
var reload      = browserSync.reload;

// Static server
gulp.task('browser-sync', function() {
  browserSync({
    server: {
      //proxy: "http://localhost:3000/",
      baseDir: "./"
    }
  });

  gulp.watch('*', ['browserSync.reload']);
});
<commit_msg>Fix autoreload<commit_after>var gulp        = require('gulp');
var browserSync = require('browser-sync');
var reload      = browserSync.reload;

gulp.task('serve', function() {
  browserSync({
    server: {
      baseDir: "./"
    }
  });

  gulp.watch(['js/*.js', 'templates/*.html', 'examples/**/*.*'], {cwd: './'}, reload);
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
mongoose.connect(process.env.MONGOLAB_URI);

var schema = mongoose.Schema({
    text: String
});

module.exports = mongoose.model('Todo', schema);
<commit_msg>MONGO_PORT_27017_TCP env variable<commit_after>var mongoose = require('mongoose');
mongoose.connect(process.env.MONGO_PORT_27017_TCP);

var schema = mongoose.Schema({
    text: String
});

module.exports = mongoose.model('Todo', schema);
<|endoftext|>


<commit_before>/* global __dirname */
'use strict';
var fs = require('fs');

var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var tagVersion = require('gulp-tag-version');
var minifyCSS = require('gulp-minify-css');

var karma = require('karma').server;

var browserSync = require('browser-sync');
var reload = browserSync.reload;

var glob = require('glob');
var runSequence = require('run-sequence');
var changelog = require('conventional-changelog');

var config = {
    app: 'app',
    build: 'build',

    server: {
        port: 3000,
        url: 'http://localhost:'
    },

    html: {
        files: [
            'app/**/*.html'
        ]
    },

    js: {
        files: [
            'gulpfile.js',
            'app/**/*.js',
            '!app/bower_components/**/*.js',
            '!app/templates.js'
        ]
    },
    scss: {
        files: [
            'app/**/*.scss',
            '!app/bower_components/**/*.scss'
        ],
        src: 'app/app.scss',
        devDest: 'app/app.css',
        buildDest: 'build/app.css'
    }
};

var release = function(importance) {
    return gulp.src(['./bower.json', './package.json'])
        .pipe($.bump({
            type: importance
        }))
        .pipe(gulp.dest('./'))
        .pipe($.git.commit('bumps package version'))
        .pipe($.filter('bower.json'))
        .pipe(tagVersion());
};

gulp.task('changelog', function(done) {
    function changeParsed(err, log) {
        if (err) {
            return done(err);
        }
        fs.writeFile('CHANGELOG.md', log, done);
    }
    fs.readFile('./package.json', 'utf8', function(err, data) {
        var ref$ = JSON.parse(data);
        var repository = ref$.repository;
        var version = ref$.version;

        changelog({
            repository: repository.url,
            version: version
        }, changeParsed);
    });
});

gulp.task('clean', function(cb) {
    require('del')([config.build], {
        force: true
    }, cb);
});

gulp.task('convert', function() {
    return gulp.src(config.app + 'bower_components/**/*.css')
        .pipe($.rename({
            extname: '.copy.scss'
        }))
        .pipe(gulp.dest(config.app + 'bower_components/'));
});

gulp.task('copy', function() {
    gulp.src(config.appDir + '**/*.html')
        .pipe(gulp.dest(config.build));
});

gulp.task('jshint', function() {
    return gulp.src(config.js.files)
        .pipe($.plumber())
        .pipe($.jshint())
        .pipe($.jshint.reporter('jshint-stylish'));
});

// gulp.task('open', function() {
//     var url = config.server.url + config.server.port;

//     require('opn')(url);
// });

gulp.task('requirejs', function() {
    $.requirejs({
            mainConfigFile: config.app + '/config.js',
            baseUrl: config.app,
            name: 'app',
            out: 'app.js',
            useStrict: true,
            optimizeCss: 'none',
            generateSourceMaps: false,
            preserveLicenseComments: true
        })
        .pipe($.uglify())
        .pipe(gulp.dest(config.build));
});

gulp.task('serve', function() {
    browserSync({
        server: {
            baseDir: './app'
        }
    });

    gulp.watch([
        '**/*.scss',
        '!bower_components/**'
    ], {
        cwd: 'app'
    }, ['scss-dev']);
});

gulp.task('scss-dev', function(cb) {
    gulp.src(config.scss.src)
        .pipe($.plumber())
        .pipe($.sourcemaps.init())
        .pipe($.sass({
            errLogToConsole: true
        }))
        .pipe($.sourcemaps.write({
            includeContent: false,
            sourceRoot: '.'
        }))
        .pipe($.sourcemaps.init({
            loadMaps: true
        }))
        .pipe($.autoprefixer())
        .pipe($.sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: '.'
        }))
        .pipe(gulp.dest(config.app))
        .pipe($.filter(config.app + '/*.css'))
        .pipe(reload({
            stream: true
        }));
    cb();
});

gulp.task('scss-build', function() {
    return gulp.src(config.scss.src)
        .pipe($.sass())
        .pipe($.autoprefixer())
        .pipe($.uncss({
            html: glob.sync('app/**/*.html')
        }))
        .pipe(minifyCSS({
            keepSpecialComments: 0
        }))
        .pipe(gulp.dest(config.build));
});

gulp.task('test', function(done) {
    karma.start({
        configFile: __dirname + '/karma.conf.js',
        singleRun: true
    }, done);
});

gulp.task('uncss', function() {
    return gulp.src(config.scss.devDest)
        .pipe($.uncss({
            html: glob.sync(config.html.files)
        }))
        .pipe(gulp.dest(config.app));
});

gulp.task('default', [
    'serve',
    'scss-dev'
]);

gulp.task('build', function() {
    runSequence('test', 'clean', 'requirejs', ['scss-build']);
});

gulp.task('patch', ['build'], function() {
    return release('patch');
});

gulp.task('feature', ['build'], function() {
    return release('minor');
});

gulp.task('release', ['build'], function() {
    return release('major');
});
<commit_msg>chore(build): Update build task<commit_after>/* global __dirname */
'use strict';
var fs = require('fs');

var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var tagVersion = require('gulp-tag-version');
var minifyCSS = require('gulp-minify-css');

var karma = require('karma').server;

var browserSync = require('browser-sync');
var reload = browserSync.reload;

var glob = require('glob');
var runSequence = require('run-sequence');
var changelog = require('conventional-changelog');

var config = {
    app: 'app',
    build: 'build',

    server: {
        port: 3000,
        url: 'http://localhost:'
    },

    html: {
        files: [
            'app/**/*.html'
        ]
    },

    js: {
        files: [
            'gulpfile.js',
            'app/**/*.js',
            '!app/bower_components/**/*.js',
            '!app/templates.js'
        ]
    },
    scss: {
        files: [
            'app/**/*.scss',
            '!app/bower_components/**/*.scss'
        ],
        src: 'app/app.scss',
        devDest: 'app/app.css',
        buildDest: 'build/app.css'
    }
};

var release = function(importance) {
    return gulp.src(['./bower.json', './package.json'])
        .pipe($.bump({
            type: importance
        }))
        .pipe(gulp.dest('./'))
        .pipe($.git.commit('bumps package version'))
        .pipe($.filter('bower.json'))
        .pipe(tagVersion());
};

gulp.task('changelog', function(done) {
    function changeParsed(err, log) {
        if (err) {
            return done(err);
        }
        fs.writeFile('CHANGELOG.md', log, done);
    }
    fs.readFile('./package.json', 'utf8', function(err, data) {
        var ref$ = JSON.parse(data);
        var repository = ref$.repository;
        var version = ref$.version;

        changelog({
            repository: repository.url,
            version: version
        }, changeParsed);
    });
});

gulp.task('clean', function(cb) {
    require('del')([config.build], {
        force: true
    }, cb);
});

gulp.task('convert', function() {
    return gulp.src(config.app + 'bower_components/**/*.css')
        .pipe($.rename({
            extname: '.copy.scss'
        }))
        .pipe(gulp.dest(config.app + 'bower_components/'));
});

gulp.task('copy', function() {
    gulp.src(config.appDir + '**/*.html')
        .pipe(gulp.dest(config.build));
});

gulp.task('jshint', function() {
    return gulp.src(config.js.files)
        .pipe($.plumber())
        .pipe($.jshint())
        .pipe($.jshint.reporter('jshint-stylish'));
});

// gulp.task('open', function() {
//     var url = config.server.url + config.server.port;

//     require('opn')(url);
// });

gulp.task('requirejs', function() {
    $.requirejs({
            mainConfigFile: config.app + '/config.js',
            baseUrl: config.app,
            name: 'app',
            out: 'app.js',
            useStrict: true,
            optimizeCss: 'none',
            generateSourceMaps: false,
            preserveLicenseComments: true
        })
        .pipe($.uglify())
        .pipe(gulp.dest(config.build));
});

gulp.task('serve', function() {
    browserSync({
        server: {
            baseDir: './app'
        }
    });

    gulp.watch([
        '**/*.scss',
        '!bower_components/**'
    ], {
        cwd: 'app'
    }, ['scss-dev']);
});

gulp.task('scss-dev', function(cb) {
    gulp.src(config.scss.src)
        .pipe($.plumber())
        .pipe($.sourcemaps.init())
        .pipe($.sass({
            errLogToConsole: true
        }))
        .pipe($.sourcemaps.write({
            includeContent: false,
            sourceRoot: '.'
        }))
        .pipe($.sourcemaps.init({
            loadMaps: true
        }))
        .pipe($.autoprefixer())
        .pipe($.sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: '.'
        }))
        .pipe(gulp.dest(config.app))
        .pipe($.filter(config.app + '/*.css'))
        .pipe(reload({
            stream: true
        }));
    cb();
});

gulp.task('scss-build', function() {
    return gulp.src(config.scss.src)
        .pipe($.sass())
        .pipe($.autoprefixer())
        .pipe($.uncss({
            html: glob.sync('app/**/*.html')
        }))
        .pipe(minifyCSS({
            keepSpecialComments: 0
        }))
        .pipe(gulp.dest(config.build));
});

gulp.task('test', function(done) {
    karma.start({
        configFile: __dirname + '/karma.conf.js',
        singleRun: true
    }, done);
});

gulp.task('uncss', function() {
    return gulp.src(config.scss.devDest)
        .pipe($.uncss({
            html: glob.sync(config.html.files)
        }))
        .pipe(gulp.dest(config.app));
});

gulp.task('default', [
    'serve',
    'scss-dev'
]);

gulp.task('build', function() {
    runSequence('test', 'clean', 'requirejs', ['scss-build'], 'changelog');
});

gulp.task('patch', ['build'], function() {
    return release('patch');
});

gulp.task('feature', ['build'], function() {
    return release('minor');
});

gulp.task('release', ['build'], function() {
    return release('major');
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var todo = require('gulp-todo');
var lint = require('gulp-eslint');

var paths = {
  src: './',
  spec: './spec/*.js',
  js: [
    './*.js',
    './src/*.js',
    './src/**/*.js',
    './scripts/**/*.js',
    './scripts/**/**/*.js',
    './commands/*.js'
  ],
};

var options = {
  todo: {
    absolute: true
  },
  lint: {
    rules: {
      'no-reserved-keys': 0,
      'no-cond-assign': 1,
      'no-dupe-args': 1,
      'no-dupe-keys': 1,
      'no-duplicate-case': 1,
      'no-extra-semi': 1,
      'no-func-assign': 1,
      'no-sparse-arrays': 1,
    },
    parserOptions: {
      'ecmaVersion': 6,
    },
  }
};

gulp.task('todo', toDoTask);

gulp.task('lint', lintTask);

gulp.task('default', ['todo', 'lint']);

function lintTask() {
  return gulp
    .src(paths.js)
    .pipe(lint(options.lint))
    .pipe(lint.format())
    .pipe(lint.failAfterError());
}

function toDoTask() {
  return gulp
    .src(paths.js)
    .pipe(todo(options.todo))
    .pipe(gulp.dest(paths.src));
}
<commit_msg>Add  lint reporter rules and enums<commit_after>var gulp = require('gulp');
var todo = require('gulp-todo');
var lint = require('gulp-eslint');

var paths = {
  src: './',
  spec: './spec/*.js',
  js: [
    './*.js',
    './src/*.js',
    './src/**/*.js',
    './scripts/**/*.js',
    './scripts/**/**/*.js',
    './commands/*.js'
  ],
};

const report = {
  ignore: 0,
  warn: 1,
  error: 2,
};

var options = {
  todo: {
    absolute: true
  },
  lint: {
    rules: {
      'no-reserved-keys':  report.ignore,

      'no-cond-assign':    report.warn,
      'no-dupe-args':      report.warn,
      'no-dupe-keys':      report.warn,
      'no-duplicate-case': report.warn,
      'no-extra-semi':     report.warn,
      'no-func-assign':    report.warn,
      'no-sparse-arrays':  report.warn,

      'no-unreachable':    report.error,

    },
    parserOptions: {
      'ecmaVersion': 6,
    },
  }
};

gulp.task('todo', toDoTask);

gulp.task('lint', lintTask);

gulp.task('default', ['todo', 'lint']);

function lintTask() {
  return gulp
    .src(paths.js)
    .pipe(lint(options.lint))
    .pipe(lint.format())
    .pipe(lint.failAfterError());
}

function toDoTask() {
  return gulp
    .src(paths.js)
    .pipe(todo(options.todo))
    .pipe(gulp.dest(paths.src));
}
<|endoftext|>


<commit_before>const $      = require('jquery')
const _      = require('lodash')
const Cycle  = require('./cycle')

var canvas   = document.getElementById('canvas');
var context  = canvas.getContext('2d');
var color    = "#31FDE8";
var color2   = "#FF1818";
var tronFont = '60px tron';
var wall     = [];

var blockSize = 2;

var cycle  = new Cycle(10, 200, blockSize, blockSize, canvas, context, color, 1, 'right');
var cycle2 = new Cycle(590, 200, blockSize, blockSize, canvas, context, color2, 1, 'left' );

requestAnimationFrame(function gameLoop() {

  updateWalls(cycle);
  updateWalls(cycle2);

  cycle.move(cycle.direction).draw();
  cycle2.move(cycle2.direction).draw();

  if ( collisionCheck(cycle)){
    context.font = tronFont;
    context.fillStyle = color;
    return context.fillText("Player 1 Wins!", 75, 190);
  }
  else if(collisionCheck(cycle2)){
    context.font = tronFont;
    context.fillStyle = color2;
    return context.fillText("Player 2 Wins!", 75, 190);
  }

  requestAnimationFrame(gameLoop);
});

function updateWalls(player) {
  if (_.find(wall, [player.x, player.y]) === undefined ) {
    wall.push([player.x, player.y]);
  }
}

function collisionCheck(player) {
  if (_.some(wall, [player.x, player.y])) {
    return true
  }
};

function playerCycleDirection (event) {
  document.addEventListener('keydown', function(event) {
    switch (event.keyCode) {

      case 65:
        cycle.direction = 'left'
        leftSpeed(cycle)
        break;

      case 37:
        cycle2.direction = 'left'
        leftSpeed(cycle2);
        break;

      case 87:
        cycle.direction = 'up'
        upSpeed(cycle);
        break;
      case 38:
        cycle2.direction = 'up'
        upSpeed(cycle2);
        break;

      case 68:
        cycle.direction = 'right';
        rightSpeed(cycle);
        break;
      case 39:
        cycle2.direction = 'right';
        rightSpeed(cycle2);
        break;

      case 83:
        cycle.direction = 'down';
        downSpeed(cycle);
        break;
      case 40:
        cycle2.direction = 'down';
        downSpeed(cycle2);
        break;
    }

    function leftSpeed(player) {
      if(player.direction === 'left') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }

    }

    function upSpeed(player) {
      if(player.direction === 'up') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }

    }

    function rightSpeed(player) {
      if(player.direction === 'down') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }

    }

    function downSpeed(player) {
      if(player.direction === 'down') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }

    }

  }, false);
}

$(document).ready( function () {
  $("#canvas").focus();
  playerCycleDirection();
});
<commit_msg>refactor direction<commit_after>const $      = require('jquery')
const _      = require('lodash')
const Cycle  = require('./cycle')

var canvas   = document.getElementById('canvas');
var context  = canvas.getContext('2d');
var color    = "#31FDE8";
var color2   = "#FF1818";
var tronFont = '60px tron';
var wall     = [];

var blockSize = 2;

var cycle  = new Cycle(10, 200, blockSize, blockSize, canvas, context, color, 1, 'right');
var cycle2 = new Cycle(590, 200, blockSize, blockSize, canvas, context, color2, 1, 'left' );

requestAnimationFrame(function gameLoop() {

  updateWalls(cycle);
  updateWalls(cycle2);

  cycle.move(cycle.direction).draw();
  cycle2.move(cycle2.direction).draw();

  if ( collisionCheck(cycle)){
    context.font = tronFont;
    context.fillStyle = color;
    return context.fillText("Player 1 Wins!", 75, 190);
  }
  else if(collisionCheck(cycle2)){
    context.font = tronFont;
    context.fillStyle = color2;
    return context.fillText("Player 2 Wins!", 75, 190);
  }

  requestAnimationFrame(gameLoop);
});

function updateWalls(player) {
  if (_.find(wall, [player.x, player.y]) === undefined ) {
    wall.push([player.x, player.y]);
  }
}

function collisionCheck(player) {
  if (_.some(wall, [player.x, player.y])) {
    return true
  }
};

function playerCycleDirection (event) {
  document.addEventListener('keydown', function(event) {
    switch (event.keyCode) {

      case 65:
        leftSpeed(cycle, 'left');
        break;

      case 37:
        leftSpeed(cycle2, 'left');
        break;

      case 87:
        upSpeed(cycle, 'up');
        break;
      case 38:
        upSpeed(cycle2, 'up');
        break;

      case 68:
        rightSpeed(cycle, 'right');
        break;
      case 39:
        rightSpeed(cycle2, 'right');
        break;

      case 83:
        downSpeed(cycle, 'down');
        break;
      case 40:
        downSpeed(cycle2, 'down');
        break;
    }

    function leftSpeed(player, direction) {
      if(player.direction === 'left') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }
      player.direction = direction;

    }

    function upSpeed(player, direction) {
      if(player.direction === 'up') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }
      player.direction = direction;

    }

    function rightSpeed(player, direction) {
      if(player.direction === 'down') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }
      player.direction = direction;

    }

    function downSpeed(player, direction) {
      if(player.direction === 'down') {
        player.speed = 2;
      } else {
        player.speed = 1;
      }
      player.direction = direction;

    }

  }, false);
}

$(document).ready( function () {
  $("#canvas").focus();
  playerCycleDirection();
});
<|endoftext|>


<commit_before>const path = require('path');

const gulp = require('gulp');
const util = require('gulp-util');
const notify = require('gulp-notify');
const plumber = require('gulp-plumber');
const changed = require('gulp-changed');
const htmlmin = require('gulp-htmlmin');
const sourcemaps = require('gulp-sourcemaps');
const htmlhint = require('gulp-htmlhint');
const stylelint = require('gulp-stylelint');
const eslint = require('gulp-eslint');
const protractor = require('gulp-protractor');

const rollup = require('rollup-stream');
const html = require('rollup-plugin-html');
const postcss = require('rollup-plugin-postcss');
const comment = require('postcss-comment');
const modules = require('postcss-modules');
const cssnext = require('postcss-cssnext');
const rucksack = require('rucksack-css');
const cssnano = require('cssnano');
const image = require('rollup-plugin-image');
const json = require('rollup-plugin-json');
const globals = require('rollup-plugin-node-globals');
const builtins = require('rollup-plugin-node-builtins');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const babel = require('rollup-plugin-babel');
const replace = require('rollup-plugin-replace');
const uglify = require('rollup-plugin-uglify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

const browsersync = require('browser-sync');
const connectHistory = require('connect-history-api-fallback');
const express = require('express');
const expressHistory = require('express-history-api-fallback');
const runsequence = require('run-sequence');

const SOURCE_ROOT = path.join(__dirname, 'src');
const DIST_ROOT = path.join(__dirname, 'dist');

class CompileError {
  static handle(err) {
    let self = this;
    if (util.env.type === 'dev') {
      let args = Array.from(arguments);

      notify.onError({
          title: 'Compile Error',
          message: `\r\n${err.message}`
        })
        .apply(this, args);

      self.emit('end');
    } else {
      util.log(`${util.colors.red(err)}`);
      process.exit(1);
    }
  }
}

class EndToEnd {
  server(port, dir) {
    let app = express();
    let root = path.resolve(process.cwd(), dir);

    app.use(express.static(root));
    app.use(expressHistory('index.html', { root }));

    return new Promise((resolve) => {
      let server = app.listen(port, () => {
        resolve(server);
      });
    });
  }
}

gulp.task('copy', () => {
  return gulp.src([
      path.join(SOURCE_ROOT, 'favicon.ico'),
      path.join(SOURCE_ROOT, 'robots.txt')
    ])
    .pipe(plumber())
    .pipe(changed(DIST_ROOT))
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

gulp.task('index', () => {
  return gulp.src(path.join(SOURCE_ROOT, 'index.html'))
    .pipe(plumber())
    .pipe(changed(DIST_ROOT))
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeAttributeQuotes: true,
      removeComments: true,
      minifyCSS: true,
      minifyJS: true
    }))
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

let [cache, cssExportMap] = [undefined, {}];
gulp.task('app', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'app.js'),
      format: 'iife',
      sourceMap: util.env.type === 'dev' && true,
      cache,
      plugins: [
        html({
          htmlMinifierOptions: {
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            removeComments: true
          }
        }),
        postcss({
          parser: comment,
          plugins: [
            cssnext({ warnForDuplicates: false }),
            rucksack({ autoprefixer: true }),
            modules({ getJSON(id, tokens) { cssExportMap[id] = tokens; } }),
            cssnano()
          ],
          getExport(id) { return cssExportMap[id]; }
        }),
        image(),
        json(),
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        babel({ exclude: 'node_modules/**' }),
        replace({ ENV: util.env.type }),
        (util.env.type === 'prod' ? uglify() : util.noop())
      ]
    })
    .on('bundle', (bundle) => { cache = bundle; })
    .on('error', CompileError.handle)
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(util.env.type === 'dev' ? sourcemaps.init({ loadMaps: true }) : util.noop())
    .pipe(util.env.type === 'dev' ? sourcemaps.write('./') : util.noop())
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

gulp.task('vendor', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'vendor.js'),
      plugins: [
        postcss({ plugins: [cssnano()] }),
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        replace({ eval: '[eval][0]' }),
        uglify()
      ]
    })
    .on('error', CompileError.handle)
    .pipe(source('vendor.js'))
    .pipe(buffer())
    .pipe(gulp.dest(DIST_ROOT));
});

gulp.task('polyfills', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'polyfills.js'),
      context: 'window',
      plugins: [
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        uglify()
      ]
    })
    .on('error', CompileError.handle)
    .pipe(source('polyfills.js'))
    .pipe(buffer())
    .pipe(gulp.dest(DIST_ROOT));
});

gulp.task('build', ['copy', 'index', 'app', 'vendor', 'polyfills']);

gulp.task('watch', () => {
  gulp.watch([
    path.join(SOURCE_ROOT, 'favicon.ico'),
    path.join(SOURCE_ROOT, 'robots.txt')
  ], ['copy']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'index.html')
  ], ['index']);

  gulp.watch([
    path.join(SOURCE_ROOT, '**/*.{html,css,js}'),
    path.join(SOURCE_ROOT, '**/*.{gif,jpeg,jpg,png,svg}'),
    path.join(SOURCE_ROOT, '**/*.json'),
    `!${path.join(SOURCE_ROOT, 'index.html')}`,
    `!${path.join(SOURCE_ROOT, 'polyfills.js')}`,
    `!${path.join(SOURCE_ROOT, 'vendor.js')}`,
    `!${path.join(SOURCE_ROOT, '**/*.{spec.js,e2e-spec.js}')}`
  ], ['app']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'vendor.js')
  ], ['vendor']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'polyfills.js')
  ], ['polyfills']);
});

gulp.task('serve', () => {
  return browsersync({
    server: {
      baseDir: DIST_ROOT,
      middleware: [connectHistory()]
    }
  });
});

gulp.task('lint-html', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.html'))
    .pipe(htmlhint('.htmlhintrc'))
    .pipe(htmlhint.reporter());
});

gulp.task('lint-css', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.css'))
    .pipe(stylelint({
      reporters: [{
        formatter: 'string', console: true
      }]
    }));
});

gulp.task('lint-js', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.js'))
    .pipe(eslint({
      useEslintrc: true
    }))
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('lint', ['lint-html', 'lint-css', 'lint-js']);

gulp.task('unit', () => {
  // ...
});

gulp.task('webdriver', protractor.webdriver_update);

gulp.task('e2e', (done) => {
  new EndToEnd()
    .server(9876, DIST_ROOT)
    .then((server) => {
      gulp.src(path.join(SOURCE_ROOT, '**/*.e2e-spec.js'))
        .pipe(protractor.protractor({
          configFile: util.env.type === 'labs' ? 'browserstack.conf.js' : 'protractor.conf.js'
        }))
        .on('error', (error) => { throw error; })
        .on('end', () => { server.close(done); });
    });
});

gulp.task('dev', (done) => {
  return runsequence('build', 'watch', 'serve', done);
});

gulp.task('dev-watch', (done) => {
  return runsequence('build', 'watch', done);
});
<commit_msg>216th Commit<commit_after>const path = require('path');

const gulp = require('gulp');
const util = require('gulp-util');
const notify = require('gulp-notify');
const plumber = require('gulp-plumber');
const changed = require('gulp-changed');
const htmlmin = require('gulp-htmlmin');
const sourcemaps = require('gulp-sourcemaps');
const htmlhint = require('gulp-htmlhint');
const stylelint = require('gulp-stylelint');
const eslint = require('gulp-eslint');
const protractor = require('gulp-protractor');

const rollup = require('rollup-stream');
const html = require('rollup-plugin-html');
const postcss = require('rollup-plugin-postcss');
const comment = require('postcss-comment');
const modules = require('postcss-modules');
const cssnext = require('postcss-cssnext');
const rucksack = require('rucksack-css');
const cssnano = require('cssnano');
const image = require('rollup-plugin-image');
const json = require('rollup-plugin-json');
const globals = require('rollup-plugin-node-globals');
const builtins = require('rollup-plugin-node-builtins');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const babel = require('rollup-plugin-babel');
const replace = require('rollup-plugin-replace');
const uglify = require('rollup-plugin-uglify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

const browsersync = require('browser-sync');
const connectHistory = require('connect-history-api-fallback');
const Karma = require('karma');
const express = require('express');
const expressHistory = require('express-history-api-fallback');
const runsequence = require('run-sequence');

const SOURCE_ROOT = path.join(__dirname, 'src');
const DIST_ROOT = path.join(__dirname, 'dist');

class CompileError {
  static handle(err) {
    let self = this;
    if (util.env.type === 'dev') {
      let args = Array.from(arguments);

      notify.onError({
          title: 'Compile Error',
          message: `\r\n${err.message}`
        })
        .apply(this, args);

      self.emit('end');
    } else {
      util.log(`${util.colors.red(err)}`);
      process.exit(1);
    }
  }
}

class Protractor {
  server(port, dir) {
    let app = express();
    let root = path.resolve(process.cwd(), dir);

    app.use(express.static(root));
    app.use(expressHistory('index.html', { root }));

    return new Promise((resolve) => {
      let server = app.listen(port, () => {
        resolve(server);
      });
    });
  }
}

gulp.task('copy', () => {
  return gulp.src([
      path.join(SOURCE_ROOT, 'favicon.ico'),
      path.join(SOURCE_ROOT, 'robots.txt')
    ])
    .pipe(plumber())
    .pipe(changed(DIST_ROOT))
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

gulp.task('index', () => {
  return gulp.src(path.join(SOURCE_ROOT, 'index.html'))
    .pipe(plumber())
    .pipe(changed(DIST_ROOT))
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeAttributeQuotes: true,
      removeComments: true,
      minifyCSS: true,
      minifyJS: true
    }))
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

let [cache, cssExportMap] = [undefined, {}];
gulp.task('app', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'app.js'),
      format: 'iife',
      context: 'window',
      sourceMap: util.env.type === 'dev' && true,
      cache,
      plugins: [
        html({
          htmlMinifierOptions: {
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            removeComments: true
          }
        }),
        postcss({
          parser: comment,
          plugins: [
            cssnext({ warnForDuplicates: false }),
            rucksack({ autoprefixer: true }),
            modules({ getJSON(id, tokens) { cssExportMap[id] = tokens; } }),
            cssnano()
          ],
          getExport(id) { return cssExportMap[id]; }
        }),
        image(),
        json(),
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        babel({ exclude: 'node_modules/**' }),
        replace({ ENV: util.env.type }),
        (util.env.type === 'prod' ? uglify() : util.noop())
      ]
    })
    .on('bundle', (bundle) => { cache = bundle; })
    .on('error', CompileError.handle)
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(util.env.type === 'dev' ? sourcemaps.init({ loadMaps: true }) : util.noop())
    .pipe(util.env.type === 'dev' ? sourcemaps.write('./') : util.noop())
    .pipe(gulp.dest(DIST_ROOT))
    .pipe(browsersync.stream());
});

gulp.task('vendor', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'vendor.js'),
      context: 'window',
      plugins: [
        postcss({ plugins: [cssnano()] }),
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        replace({ eval: '[eval][0]' }),
        uglify()
      ]
    })
    .on('error', CompileError.handle)
    .pipe(source('vendor.js'))
    .pipe(buffer())
    .pipe(gulp.dest(DIST_ROOT));
});

gulp.task('polyfills', () => {
  return rollup({
      entry: path.join(SOURCE_ROOT, 'polyfills.js'),
      context: 'window',
      plugins: [
        globals(),
        builtins(),
        resolve({ jsnext: true, browser: true }),
        commonjs(),
        uglify()
      ]
    })
    .on('error', CompileError.handle)
    .pipe(source('polyfills.js'))
    .pipe(buffer())
    .pipe(gulp.dest(DIST_ROOT));
});

gulp.task('build', ['copy', 'index', 'app', 'vendor', 'polyfills']);

gulp.task('watch', () => {
  gulp.watch([
    path.join(SOURCE_ROOT, 'favicon.ico'),
    path.join(SOURCE_ROOT, 'robots.txt')
  ], ['copy']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'index.html')
  ], ['index']);

  gulp.watch([
    path.join(SOURCE_ROOT, '**/*.{html,css,js}'),
    path.join(SOURCE_ROOT, '**/*.{gif,jpeg,jpg,png,svg}'),
    path.join(SOURCE_ROOT, '**/*.json'),
    `!${path.join(SOURCE_ROOT, 'index.html')}`,
    `!${path.join(SOURCE_ROOT, 'polyfills.js')}`,
    `!${path.join(SOURCE_ROOT, 'vendor.js')}`,
    `!${path.join(SOURCE_ROOT, '**/*.{spec.js,e2e-spec.js}')}`
  ], ['app']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'vendor.js')
  ], ['vendor']);

  gulp.watch([
    path.join(SOURCE_ROOT, 'polyfills.js')
  ], ['polyfills']);
});

gulp.task('serve', () => {
  return browsersync({
    server: {
      baseDir: DIST_ROOT,
      middleware: [connectHistory()]
    }
  });
});

gulp.task('lint-html', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.html'))
    .pipe(htmlhint('.htmlhintrc'))
    .pipe(htmlhint.reporter());
});

gulp.task('lint-css', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.css'))
    .pipe(stylelint({
      reporters: [{
        formatter: 'string', console: true
      }]
    }));
});

gulp.task('lint-js', () => {
  return gulp.src(path.join(SOURCE_ROOT, '**/*.js'))
    .pipe(eslint({
      useEslintrc: true
    }))
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('lint', ['lint-html', 'lint-css', 'lint-js']);

gulp.task('unit', (done) => {
  new Karma.Server({
    configFile: path.join(__dirname, 'karma.conf.js')
  }, done).start();
});

gulp.task('webdriver', protractor.webdriver_update);

gulp.task('e2e', (done) => {
  new Protractor()
    .server(9876, DIST_ROOT)
    .then((server) => {
      gulp.src(path.join(SOURCE_ROOT, '**/*.e2e-spec.js'))
        .pipe(protractor.protractor({
          configFile: util.env.type === 'labs' ? 'browserstack.conf.js' : 'protractor.conf.js'
        }))
        .on('error', (error) => { throw error; })
        .on('end', () => { server.close(done); });
    });
});

gulp.task('dev', (done) => {
  return runsequence('build', 'watch', 'serve', done);
});

gulp.task('dev-watch', (done) => {
  return runsequence('build', 'watch', done);
});
<|endoftext|>