define('worker_console', function () {
  var window = this;
  var counter = 0;
  if (window.document === undefined && window.console === undefined) {
    console = ([
        'log'
      , 'warn'
      , 'error'
      , 'debug'
      , 'group'
      , 'groupEnd'
    ].reduce(
        function (o, func) {
          o[func] = function () {
            postMessage({ cmd: 'console', func: func, arguments: arguments, stack: (new Error).stack, count: counter++ });
          };
          return o;
        }
      , {}
    ));
    console.worker = true;
  } else {
    console.wrapWorker = function (worker) {
      worker.addEventListener('message', function (event) {
        if (event.data.cmd !== 'console')
          return true;
        console[event.data.func].bind(console)(event.data.arguments, event.data.stack.split('\n')[2], event.data.count);
        event.stopImmediatePropagation();
      });
      worker.addEventListener('error', function (event) {
        console.error(event);
      });
      return worker;
    }
  }
  return console;
});

define('worker_console', function () {
  var window = this;
  var counter = 0;
  if (window.document === undefined) {
    if (window.console === undefined) {
      console = ([
          'log'
        , 'warn'
        , 'error'
        , 'debug'
        , 'group'
        , 'groupEnd'
        , 'time'
        , 'timeEnd'
      ].reduce(
          function (o, func) {
            o[func] = function () {
              this._channel.port1.postMessage({ func: func, arguments: Array.prototype.slice.call(arguments), stack: (new Error).stack, count: counter++ });
            };
            return o;
          }
        , {}
      ));
      console._channel = new MessageChannel;
      postMessage('console', [console._channel.port2]);
      console.worker = true;
    } else {
      postMessage('consolenotrequired');
    }
  } else {
    console.wrapWorker = function (worker) {
      worker._console_port = null;
      function messageHandler (event) {
        if (event.data === 'consolenotrequired') {
          worker.removeEventListener('message', messageHandler);
          event.stopImmediatePropagation();
          return false;
        }
        if (event.data !== 'console')
          return true;
        worker._console_port = event.ports[0];
        worker._console_port.onmessage = function (event) {
          console.error(event, event.data)
          var data = event.data
            , args = data.arguments;
          args.push('\tFrom worker ' + data.stack.split('\n')[2].trimLeft());
          console[data.func].apply(console, args);
        }
        worker.removeEventListener('message', messageHandler);
        event.stopImmediatePropagation();
        return false;
      }
      worker.addEventListener('message', messageHandler);
      worker.addEventListener('error', function (event) {
        console.error(event);
      });
      return worker;
    }
  }
  return console;
});

Use MessageChannel for console.log, allow time/timeEnd, better handling of Chrome WebWorker console Should be quicker than waiting for large queues of requests


/**
 * The client JS file that brings in React and bootstraps the app into the page from the server state.
 */
import React from "react";
import App from "./app";

//put React into the global scope For chrome dev tool support
window.React = React;
//grab the app node
const mountNode = document.getElementById('app');
//render our app component into that node
React.render(<App/>, mountNode);

/**
 * The client JS file that brings in React and bootstraps the app into the page from the server state.
 */
import React from "react";
import App from "./app";

//put React into the global scope for chrome dev tool support
window.React = React;
//grab the app node
const mountNode = document.getElementById('app');
//render our app component into that node
React.render(<App/>, mountNode);

Change For to lowercase for


const fs = require('fs');
const join = require('path').join;
const sep = require('path').sep;

const files = [];
function crawl(location: string) {
  const dir = fs.readdirSync(location);
  dir.map(function(name, index) {
    const stat = fs.statSync(join(location, name));
    if (stat.isDirectory()) {
      crawl(join(location, name));
    } else {
      files.push(join(location, name));
    }
  });
}
crawl('docs');

const names = files.map(function (file) {
  const nameWithExt = file.split('docs'+sep)[1];
  const name = nameWithExt.split('.md')[0];
  return name;
});

const mdData = {};

names.map(function (name) {
  mdData[name] = fs.readFileSync('docs' + sep + name + '.md', { encoding: 'utf8' });
});

fs.writeFileSync('website' + sep + 'docs-dist.json', JSON.stringify(mdData));
//testsdfsdfsssssaaaaaaaaaaaa sfdaf asd sfda

Make America cross-platform again (multiplatform install scripts)


import $ from 'jquery';

// bootstrap jQuery plugins
import 'bootstrap';

// custom jQuery functions
$.fn.extend({
  disable() {
    return $(this)
      .prop('disabled', true)
      .addClass('disabled');
  },
  enable() {
    return $(this)
      .prop('disabled', false)
      .removeClass('disabled');
  },
});

/*
 Starting with bootstrap 4.3.1, bootstrap sanitizes html used for tooltips / popovers.
 This extends the default whitelists with more elements / attributes:
 https://getbootstrap.com/docs/4.3/getting-started/javascript/#sanitizer
 */
const whitelist = $.fn.tooltip.Constructor.Default.whiteList;

const inputAttributes = ['value', 'type'];

const dataAttributes = [
  'data-toggle',
  'data-placement',
  'data-container',
  'data-title',
  'data-class',
  'data-clipboard-text',
  'data-placement',
];

// Whitelisting data attributes
whitelist['*'] = [
  ...whitelist['*'],
  ...dataAttributes,
  'title',
  'width height',
  'abbr',
  'datetime',
  'name',
  'width',
  'height',
];

// Whitelist missing elements:
whitelist.label = ['for'];
whitelist.button = [...inputAttributes];
whitelist.input = [...inputAttributes];

whitelist.tt = [];
whitelist.samp = [];
whitelist.kbd = [];
whitelist.var = [];
whitelist.dfn = [];
whitelist.cite = [];
whitelist.big = [];
whitelist.address = [];
whitelist.dl = [];
whitelist.dt = [];
whitelist.dd = [];
whitelist.abbr = [];
whitelist.acronym = [];
whitelist.blockquote = [];
whitelist.del = [];
whitelist.ins = [];
whitelist['gl-emoji'] = [];

// Whitelisting SVG tags and attributes
whitelist.svg = ['viewBox'];
whitelist.use = ['xlink:href'];
whitelist.path = ['d'];

Whitelist additional elements and attributes


var path = require('path');
var findParentDir = require('find-parent-dir');
var fs = require('fs');

function resolve(targetUrl, source) {
  var packageRoot = findParentDir.sync(source, 'node_modules');

  if (!packageRoot) {
    return null;
  }

  var filePath = path.resolve(packageRoot, 'node_modules', targetUrl);
  var isPotentiallyDirectory = !path.extname(filePath);

  if (isPotentiallyDirectory) {
    if (s.existsSync(filePath + '.scss')) {
      return path.resolve(filePath, 'index');
    }

    if (fs.existsSync(filePath)) {
      return path.resolve(filePath, 'index');
    }
  }

  if (fs.existsSync(path.dirname(filePath))) {
    return filePath;
  }

  return resolve(targetUrl, path.dirname(packageRoot));
}

module.exports = function importer (url, prev, done) {
  return (url[ 0 ] === '~') ? { file: resolve(url.substr(1), prev) } : null;
};

var path = require('path');
var findParentDir = require('find-parent-dir');
var fs = require('fs');

function resolve(targetUrl, source) {
  var packageRoot = findParentDir.sync(source, 'node_modules');

  if (!packageRoot) {
    return null;
  }

  var filePath = path.resolve(packageRoot, 'node_modules', targetUrl);
  var isPotentiallyDirectory = !path.extname(filePath);

  if (isPotentiallyDirectory) {
    if (fs.existsSync(filePath + '.scss')) {
      return path.resolve(filePath, 'index');
    }

    if (fs.existsSync(filePath)) {
      return path.resolve(filePath, 'index');
    }
  }

  if (fs.existsSync(path.dirname(filePath))) {
    return filePath;
  }

  return resolve(targetUrl, path.dirname(packageRoot));
}

module.exports = function importer (url, prev, done) {
  return (url[ 0 ] === '~') ? { file: resolve(url.substr(1), prev) } : null;
};

Fix typo on fs variable name


define([
  'extensions/controllers/module',
  'common/views/visualisations/bar_chart_with_number',
  'common/collections/bar_chart_with_number'
],
function (ModuleController, BarChartWithNumberView, BarChartWithNumberCollection) {
  var BarChartWithNumberModule = ModuleController.extend({
    visualisationClass: BarChartWithNumberView,
    collectionClass: BarChartWithNumberCollection,
    clientRenderOnInit: true,
    requiresSvg: true,

    collectionOptions: function () {
      var valueAttr = this.model.get('value-attribute');
      var options = {
        queryParams: this.model.get('query-params'),
        valueAttr: valueAttr,
        axisPeriod: this.model.get('axis-period')
      };
      options.format = this.model.get('format') ||
        { type: 'integer', magnitude: true, sigfigs: 3 };

      options.axes = _.merge({
          x: {
            label: 'Dates',
            key: ['_start_at', 'end_at'],
            format: 'dateRange'
          },
          y: [
            {
              label: 'Number of applications',
              key: valueAttr,
              format: options.format
            }
          ]
        }, this.model.get('axes'));
      return options;
    },

    visualisationOptions: function () {
      return _.defaults(ModuleController.prototype.visualisationOptions.apply(this, arguments), {
        valueAttr: 'uniqueEvents',
        formatOptions: this.model.get('format')
      });
    }
  });

  return BarChartWithNumberModule;
});

define([
  'extensions/controllers/module',
  'common/views/visualisations/bar_chart_with_number',
  'common/collections/bar_chart_with_number'
],
function (ModuleController, BarChartWithNumberView, BarChartWithNumberCollection) {
  var BarChartWithNumberModule = ModuleController.extend({
    visualisationClass: BarChartWithNumberView,
    collectionClass: BarChartWithNumberCollection,
    clientRenderOnInit: true,
    requiresSvg: true,

    collectionOptions: function () {
      var valueAttr = this.model.get('value-attribute');
      var options = {
        queryParams: this.model.get('query-params'),
        valueAttr: valueAttr,
        axisPeriod: this.model.get('axis-period')
      };
      options.format = this.model.get('format') ||
        { type: 'integer', magnitude: true, sigfigs: 3, pad: true };

      options.axes = _.merge({
          x: {
            label: 'Dates',
            key: ['_start_at', 'end_at'],
            format: 'dateRange'
          },
          y: [
            {
              label: 'Number of applications',
              key: valueAttr,
              format: options.format
            }
          ]
        }, this.model.get('axes'));
      return options;
    },

    visualisationOptions: function () {
      return _.defaults(ModuleController.prototype.visualisationOptions.apply(this, arguments), {
        valueAttr: 'uniqueEvents',
        formatOptions: this.model.get('format')
      });
    }
  });

  return BarChartWithNumberModule;
});

Update default formatting for bar chart module


'use strict';

const express = require('express');
const APP_CONST = require('../constant/app');

class Server {
  /**
   * Constructor
   * @param config
   */
  constructor(config) {
    this.config = config || {};
    this.core = express();
  }

  /**
   * Initial middleware
   * @private
   */
  _initMiddleware() {}

  /**
   * Initial router
   * @private
   */
  _initRouter() {}

  /**
   * Boot server
   * @private
   */
  _boot() {
    this.core.listen(APP_CONST.PORT, console.log(`line bot server listened on ${APP_CONST.PORT}`));
  }

  /**
   * Boot server
   */
  boot() {
    this._initMiddleware();
    this._initRouter();
    this._boot();
  }

  /**
   * Halt server
   * @private
   */
  _halt() {
    process.exit();
  }

  /**
   * Halt server
   */
  halt() {
    this._halt();
  }
}

module.exports = Server;

'use strict';

const bodyParser = require('body-parser');
const express = require('express');
const APP_CONST = require('../constant/app');

class Server {
  /**
   * Constructor
   * @param config
   */
  constructor(config) {
    this.config = config || {};
    this.core = express();
  }

  /**
   * Initial middleware
   * @private
   */
  _initMiddleware() {
    this.core.use(bodyParser.json());
  }

  /**
   * Initial router
   * @private
   */
  _initRouter() {}

  /**
   * Boot server
   * @private
   */
  _boot() {
    this.core.listen(APP_CONST.PORT, console.log(`line bot server listened on ${APP_CONST.PORT}`));
  }

  /**
   * Boot server
   */
  boot() {
    this._initMiddleware();
    this._initRouter();
    this._boot();
  }

  /**
   * Halt server
   * @private
   */
  _halt() {
    process.exit();
  }

  /**
   * Halt server
   */
  halt() {
    this._halt();
  }
}

module.exports = Server;

Use body parser parsing request body


import $ from 'jquery';
import { later, cancel } from '@ember/runloop';
import { inject as service } from '@ember/service';
import Router from '../router';

export default {
  name: 'add-announcer-to-router',
  initialize: function() {
    Router.reopen({
      announcer: service('announcer'),
      didTransition: function() {
        this._super(...arguments);

        this._timerId = later(() => {
          if (this.isDestroying || this.isDestroyed) { return; }

          let pageTitle = $('title').html().trim();
          let serviceMessage = this.get('announcer.message');
          let message = `${pageTitle} ${serviceMessage}`;

          this.get('announcer').announce(message, 'polite');
        }, 100);
      },

      willDestroy() {
        cancel(this._timerId);
        this._super();
      }
    });
  }
};

import { later, cancel } from '@ember/runloop';
import { inject as service } from '@ember/service';
import Router from '../router';

export default {
  name: 'add-announcer-to-router',

  initialize() {

    Router.reopen({
      announcer: service('announcer'),

      didTransition() {
        this._super(...arguments);

        this._timerId = later(() => {
          if (this.isDestroying || this.isDestroyed) { return; }

          let pageTitle = document.title.trim();
          let serviceMessage = this.get('announcer.message');
          let message = `${pageTitle} ${serviceMessage}`;

          this.get('announcer').announce(message, 'polite');
        }, 100);
      },

      willDestroy() {
        cancel(this._timerId);
        this._super();
      }
    });

  }
};

Remove jquery usage & replace with dom apis


const merge = require("webpack-merge");
const PostCompile = require("post-compile-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const Version = require("node-version-assets");
const common = require("./webpack.common.js");

const postCSSPlugins = [
  require("postcss-easy-import")({ prefix: "_" }),
  require("postcss-mixins"),
  require("postcss-simple-vars"),
  require("postcss-nested"),
  require("postcss-color-function"),
  require("postcss-hexrgba"),
  require("autoprefixer"),
  require("cssnano")
];

module.exports = env => {
  const opt = env || {};

  return merge(common, {
    mode: "production",
    plugins: opt.deploy && [
      new PostCompile(() => {
        new Version({
          assets: [
            "./src/_compiled/main.css",
            "./src/_compiled/main.js",
            "./src/_compiled/vendors~main.js",
            "./src/_compiled/runtime~main.js"
          ],
          grepFiles: ["./src/index.html"]
        }).run();
      })
    ],
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            {
              loader: "css-loader",
              options: {
                url: false
              }
            },
            {
              loader: "postcss-loader",
              options: {
                plugins: postCSSPlugins
              }
            }
          ]
        }
      ]
    }
  });
};

const merge = require("webpack-merge");
const PostCompile = require("post-compile-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const Version = require("node-version-assets");

const postCSSPlugins = [
  require("postcss-easy-import")({ prefix: "_" }),
  require("postcss-mixins"),
  require("postcss-simple-vars"),
  require("postcss-nested"),
  require("postcss-color-function"),
  require("postcss-hexrgba"),
  require("autoprefixer"),
  require("cssnano")
];

const common = require("./webpack.common.js");

module.exports = env => {
  const opt = env || {};

  return merge(common, {
    mode: "production",
    plugins: opt.deploy && [
      new PostCompile(() => {
        new Version({
          assets: [
            "./src/_compiled/main.css",
            "./src/_compiled/main.js",
            "./src/_compiled/vendors~main.js",
            "./src/_compiled/runtime~main.js"
          ],
          grepFiles: ["./src/index.html"]
        }).run();
      })
    ],
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            {
              loader: "css-loader",
              options: {
                url: false
              }
            },
            {
              loader: "postcss-loader",
              options: {
                plugins: postCSSPlugins
              }
            }
          ]
        }
      ]
    }
  });
};

Correct linting error with order of requires


// Listen for nav clicks

document.body.addEventListener('click', function (event) {
  if (event.target.classList.contains('nav-link')) {
    var viewId = '#' + event.target.dataset.view + '-view';
    removeSelectedShow();
    event.target.classList.add('is-selected');
    document.querySelector(viewId).classList.add('show');
  }
});

function removeSelectedShow () {
  if (document.querySelector('.is-selected')) {
    document.querySelector('.is-selected').classList.remove('is-selected');
  }
  document.querySelector('.show').classList.remove('show');
}

// Listen for nav clicks

document.body.addEventListener('click', function (event) {
  if (classContains('nav-link') || classContains('nav-footer-link')) {
    var viewId = '#' + event.target.dataset.view + '-view';
    removeSelectedShow();
    event.target.classList.add('is-selected');
    document.querySelector(viewId).classList.add('show');
  }
});

function classContains (className) {
  return event.target.classList.contains(className)
}

function removeSelectedShow () {
  if (document.querySelector('.is-selected')) {
    document.querySelector('.is-selected').classList.remove('is-selected');
  }
  document.querySelector('.show').classList.remove('show');
}

Add helper function and look for about button class also


'use strict';

var resolve  = require('path').resolve
  , stat     = require('fs2/stat')
  , readFile = require('fs2/read-file')

  , create = Object.create;

module.exports = function () {
	var cache = create(null);

	return function (path) {
		path = resolve(path);
		return stat(path)(function (stats) {
			var etag = stats.size + '.' + stats.mtime.valueOf();
			if (cache[path]) {
				if (cache[path].etag === etag) return cache[path].data;
				cache[path].etag = etag;
			} else {
				cache[path] = { etag: etag };
			}
			return (cache[path].data = readFile(path, 'utf8'));
		});
	};
};

'use strict';

var resolve  = require('path').resolve
  , stat     = require('fs2/stat')
  , readFile = require('fs2/read-file')

  , create = Object.create;

module.exports = function () {
	var cache = create(null);

	return function (path/*, options*/) {
		var options = Object(arguments[1]);
		path = resolve(path);
		return stat(path)(function (stats) {
			var etag = stats.size + '.' + stats.mtime.valueOf();
			if (cache[path]) {
				if (cache[path].etag === etag) return cache[path].data;
				cache[path].etag = etag;
			} else {
				cache[path] = { etag: etag };
			}
			return (cache[path].data = readFile(path, 'utf8'));
		}, options.loose ? function (err) {
			if (err.code !== 'ENOENT') throw err;
			return null;
		} : null);
	};
};

Support readFile options in getReadFile


import * as t from '../action-types'
import { createAction } from './create-action'
import AuthSelectors from '~client/account/redux/selectors'

export default mobilizationId => (dispatch, getState, { api }) => {
  const headers = AuthSelectors(getState()).getCredentials()
  dispatch(createAction(t.FETCH_BLOCKS_REQUEST))
  return api
    .get(`/mobilizations/${mobilizationId}/blocks`, { headers })
    .then(response => {
      dispatch(createAction(t.FETCH_BLOCKS_SUCCESS, response.data))
      return Promise.resolve()
    })
    .catch(ex => {
      dispatch(createAction(c.FETCH_BLOCKS_FAILURE, ex))
      return Promise.reject(ex)
    })
}

import * as t from '../action-types'
import { createAction } from './create-action'
import AuthSelectors from '~client/account/redux/selectors'

export default mobilizationId => (dispatch, getState, { api }) => {
  const headers = AuthSelectors(getState()).getCredentials()
  dispatch(createAction(t.FETCH_BLOCKS_REQUEST))
  return api
    .get(`/mobilizations/${mobilizationId}/blocks`, { headers })
    .then(response => {
      dispatch(createAction(t.FETCH_BLOCKS_SUCCESS, response.data))
      return Promise.resolve()
    })
    .catch(ex => {
      dispatch(createAction(t.FETCH_BLOCKS_FAILURE, ex))
      return Promise.reject(ex)
    })
}

Fix failure type on fetch blocks action


Elm.Time = function() {
  var every = function(t) {
      t *= 1000;
      var clock = Elm.Signal.constant(0);
      var time = 0;
      setInterval(function() {
	      time += t;
	      Dispatcher.notify(clock.id, time/1000);
	  }, t);
      return clock;
  };
  var after = function(t) {
      t *= 1000;
      var thread = Elm.Signal.constant(false);
      setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
      return thread;
  };
  var before = function(t) {
      t *= 1000;
      var thread = Elm.Signal.constant(true);
      setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
      return thread;
  };
  return {every:every,after:after,before:before};
}();

Elm.Time = function() {
  var now = function(t) {
      var clock = Elm.Signal.constant((new Date()).getTime());
      function tellTime() { Dispatcher.notify(clock.id, (new Date()).getTime()); }
      setInterval(tellTime, t);
      return clock;
  };
  var every = function(t) {
      t *= 1000;
      var clock = Elm.Signal.constant(0);
      var time = 0;
      setInterval(function() {
	      time += t;
	      Dispatcher.notify(clock.id, time/1000);
	  }, t);
      return clock;
  };
  var after = function(t) {
      t *= 1000;
      var thread = Elm.Signal.constant(false);
      setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
      return thread;
  };
  var before = function(t) {
      t *= 1000;
      var thread = Elm.Signal.constant(true);
      setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
      return thread;
  };
  function read(s) {
      var t = Date.parse(s);
      return isNaN(t) ? Nothing : Just(s);
  }
  return {now:now,
	  every:every,
	  after:after,
	  before:before,
	  hours : function(n) { return n * 3600000; },
	  minutes : function(n) { return n * 60000; },
	  seconds : function(n) { return n * 1000; },
	  millis : function(n) { return n; },
	  inHours : function(t) { return ~~(t / 3600000); },
	  inMinutes : function(t) { return ~~(t / 60000); },
	  inSeconds : function(t) { return ~~(t / 1000); },
	  inMillis : function(t) { return t; },
	  toDate : function(t) { return new Date(t); },
	  read : read
  };

}();

Add `now` and lots of time conversions to time library


/* jshint node: true */
'use strict';

module.exports = {
    name: 'ember-cli-hot-loader',
    serverMiddleware: function (config){
        if (config.options.environment === 'development') {
            var lsReloader = require('./lib/hot-reloader')(config.options);
            lsReloader.run();
        }
    },
    included: function (app) {
        this._super.included(app);

        // If not in dev, bail
        if (app.env !== 'development') {
            return;
        }

        const bowerPath = app.bowerDirectory + '/ember/ember-template-compiler.js';
        const npmPath = app.project.nodeModulesPath + '/ember-source/dist/ember-template-compiler.js';

        // Require template compiler as in CLI this is only used in build, we need it at runtime
        if (fs.existsSync(bowerPath)) {
            app.import(bowerPath);
        }

        if (fs.existsSync(npmPath)) {
            app.import(npmPath);
        }
    }
};

/* jshint node: true */
'use strict';

module.exports = {
    name: 'ember-cli-hot-loader',
    serverMiddleware: function (config){
        if (config.options.environment === 'development') {
            var lsReloader = require('./lib/hot-reloader')(config.options);
            lsReloader.run();
        }
    },
    included: function (app) {
        this._super.included(app);

        // If not in dev, bail
        if (app.env !== 'development') {
            return;
        }

        const bowerPath = app.bowerDirectory + '/ember/ember-template-compiler.js';
        const npmPath = app.project.nodeModulesPath + '/ember-source/dist/ember-template-compiler.js';

        // Require template compiler as in CLI this is only used in build, we need it at runtime
        if (fs.existsSync(bowerPath)) {
            app.import(bowerPath);
        } else if (fs.existsSync(npmPath)) {
            app.import(npmPath);
        } else {
            throw new Error('Unable to locate ember-template-compiler.js. ember/ember-source not found in either bower_components or node_modules');
        }
    }
};

Throw error if ember-template-compiler.js not found


import React, { Component } from 'react';
import { View, TextInput, Text, StyleSheet, TouchableOpacity } from 'react-native';

export default class SearchBar extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.searchBarContainer}>
          <View style={styles.searchInput}>
            <TextInput style={styles.searchBar} underlineColorAndroid='transparent'/>
          </View>

          <View style={styles.searchButton}>
            <Text>Search</Text>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 80,
    paddingHorizontal: 16,
  },
  searchBar: {
    fontSize: 22,
    paddingVertical: 5,
    paddingHorizontal: 6
  },
  searchBarContainer: {
    borderRadius: 6,
    elevation: 3,
    backgroundColor: 'white',
    flexDirection: 'row',
  },
  searchInput: {
    flex: 0.8,
    borderRadius: 6,
  },
  searchButton: {
    flex: 0.2,
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 2,
  }
});

import React, { Component } from 'react';
import { View, TextInput, Text, StyleSheet, TouchableOpacity, ToastAndroid } from 'react-native';

export default class SearchBar extends Component {
  static defaultProps = {
    searchButton: <Text>Search</Text>,
    searchOnPress: () => ToastAndroid.show('Pressed', ToastAndroid.SHORT)
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.searchBarContainer}>
          <View style={styles.searchInput}>
            <TextInput style={styles.searchBar} underlineColorAndroid='transparent'/>
          </View>

          <View style={styles.searchButton}>
            <TouchableOpacity onPress={this.props.searchOnPress}>
              {this.props.searchButton}
            </TouchableOpacity>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 80,
    paddingHorizontal: 16,
  },
  searchBar: {
    fontSize: 22,
    paddingVertical: 5,
    paddingHorizontal: 6
  },
  searchBarContainer: {
    borderRadius: 6,
    elevation: 3,
    backgroundColor: 'white',
    flexDirection: 'row',
  },
  searchInput: {
    flex: 0.8,
    borderRadius: 6,
  },
  searchButton: {
    flex: 0.2,
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 2,
  }
});

Add button to search bar


const express = require('express');
const app = express();

app.get('/', function (req, res) {
  res.send('a');
});

const server = app.listen(8080, function () {
  const host = server.address().address;
  const port = server.address().port;
  console.log("http://%s:%s", host, port);
});

const express = require('express');
const app = express();

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('db.sqlite3');

app.get('/', function (req, res) {
  res.send('a');
});

// put successfull signal
app.get('/r/:rId', function (req, res) {
  const rId = req.params.rId;

  res.send("Ok. " + rId);
});

app.post('/new', function (req, res) {
  let url = req.body.url;
  // TODO : query parser to json
  let form_data = req.body.form_data;

  db.serialize(function () {
    const insert = db.prepare("insert into valid_xss_checker (url, form_data) values (?, ?)");
    insert.run(url, form_data);
    insert.finalize();
    db.each("select last_insert_rowid() from valid_xss_checker limit 1;", function (err, row) {
      let response = Object();
      response.rId = row['last_insert_rowid()'];
      response.url = url;
      response.form_data = form_data;
      res.send(JSON.stringify(response));
    });
  });
});

const server = app.listen(8080, function () {
  const host = server.address().address;
  const port = server.address().port;
  console.log("http://%s:%s", host, port);
});

Add make new xss check func


var color = require("color");

var Radient = function(obj) {
  if (obj instanceof Radient) return obj;

  this.stops = [];

  for (var i = 0; i < arguments.length; i++)
    this.stops.push({ color: new color(arguments[i]), location: null });

  this.distribute();
}

Radient.prototype.distribute = function()
{
  n = 1 / (this.stops.length - 1);

  for (var i = 0; i < this.stops.length; i++)
    this.stops[i].location = i * n;
}

Radient.prototype.stop = function(color, location)
{
}

Radient.prototype.color = function(location)
{
}

Radient.prototype.angle = function(degrees)
{
}

Radient.prototype.array = function(stops)
{
}

Radient.prototype.toString = function()
{
  if (this.stops.length == 0) throw new Error("Gradients must have at least two stops");

  r = [] ;

  this.stops.forEach(function(element) {
    r.push(element.location + ' ' + element.color.hexString());
  });

  return r.join("\n");
}

module.exports = Radient;

var color = require("color");

var Radient = function(obj) {
  if (obj instanceof Radient) return obj;

  this.stops = [];

  for (var i = 0; i < arguments.length; i++)
    this.stops.push({ color: new color(arguments[i]), location: null });

  this.distribute();
}

Radient.prototype.distribute = function()
{
  n = 1 / (this.stops.length - 1);

  for (var i = 0; i < this.stops.length; i++)
    this.stops[i].location = i * n;
}

Radient.prototype.stop = function(c, l)
{
  l = parseFloat(l);

  if(isNaN(l)) throw new Error("Unable to determine stop location: " + l);

  this.stops.push({ color: new color(c), location: l });

  this.sort();
}

Radient.prototype.sort = function()
{
  this.stops.sort(function (a, b) {
    return a.location - b.location;
  });
}

Radient.prototype.color = function(location)
{
}

Radient.prototype.angle = function(degrees)
{
}

Radient.prototype.array = function(stops)
{
  if (this.stops.length < 2) throw new Error("Gradients must have at least two stops");
}

Radient.prototype.toString = function()
{
  if (this.stops.length == 0) return 'empty gradient';

  r = [];

  this.stops.forEach(function(element) {
    r.push(element.location + ' ' + element.color.hexString());
  });

  return r.join("\n");
}

module.exports = Radient;

var g = new Radient();
g.stop('#fff', .2);
g.stop('#fff', 0);
console.log(g + '');

Implement addition of stops via function; Sort stops by location;


var stati = [
    'irritable',
    'gassy',
    'diuretic',
    'constipated',
    'twisted',
    'cramped',
    'surly',
    'churlish',
    'hungry',
    'famished'
    // Have another idea? Submit a pull request or issue
    // https://github.com/itsananderson/gut-status/issues
];

function getStatus() {
    var index = Math.floor(Math.random() * stati.length);
    return stati[index];
}

module.exports = {
    stati: stati,
    getStatus: getStatus
};

var stati = [
    'irritable',
    'gassy',
    'diuretic',
    'constipated',
    'twisted',
    'cramped',
    'surly',
    'churlish',
    'hungry',
    'famished',
    'A little nauseous, actually. Yours?'
    // Have another idea? Submit a pull request or issue
    // https://github.com/itsananderson/gut-status/issues
];

function getStatus() {
    var index = Math.floor(Math.random() * stati.length);
    return stati[index];
}

module.exports = {
    stati: stati,
    getStatus: getStatus
};

Add a new gut status


/* eslint-env node */
'use strict';

var path = require('path');
var Funnel = require('broccoli-funnel');
var MergeTrees = require('broccoli-merge-trees');

module.exports = {
  name: 'ember-launch-darkly',

  isDevelopingAddon() {
    return true;
  },

  included(app) {
    this._super.included.apply(this, arguments);

    if (!this._registeredWithBabel) {
      app.options = app.options || {};
      app.options.babel = app.options.babel || {};
      app.options.babel.plugins = app.options.babel.plugins || [];

      app.options.babel.plugins.unshift(require('./launch-darkly-variation-helper.js'));

      this._registeredWithBabel = true;
    }

    this.import('vendor/ldclient.js');
  },

  treeForVendor(vendorTree) {
    var ldTree = new Funnel(path.dirname(require.resolve('ldclient-js/dist/ldclient.js')), {
      files: ['ldclient.js'],
    });

    return new MergeTrees([vendorTree, ldTree]);
  }
};

/* eslint-env node */
'use strict';

var path = require('path');
var Funnel = require('broccoli-funnel');
var MergeTrees = require('broccoli-merge-trees');

module.exports = {
  name: 'ember-launch-darkly',

  isDevelopingAddon() {
    return true;
  },

  included(app) {
    this._super.included.apply(this, arguments);

    if (!this._registeredWithBabel) {
      app.options = app.options || {};
      app.options.babel = app.options.babel || {};
      app.options.babel.plugins = app.options.babel.plugins || [];

      app.options.babel.plugins.unshift(require('./launch-darkly-variation-helper.js'));

      this._registeredWithBabel = true;
    }

    this.import('vendor/ldclient.js');
  },

  treeForVendor(vendorTree) {
    var ldTree = new Funnel(path.dirname(require.resolve('ldclient-js/dist/ldclient.js')), {
      files: ['ldclient.js'],
    });

    return vendorTree ? new MergeTrees([vendorTree, ldTree]) : ldTree;
  }
};

Fix bug where vendorTree is undefined


/* jshint node: true */
'use strict';

var fs = require('fs');
var path = require('path');

function readSnippet() {
  try {
    // NOTE: expecting addon as a node_module on parent addon or in an Ember CLI application.
    return fs.readFileSync(path.join(process.cwd(), 'node_modules/ember-segmentio/vendor/snippet-core.min.js'), {
      encoding: 'UTF-8'
    });
  } catch(error) {
    if (error.code === 'ENOENT') {
      return '';
    } else {
      throw error;
    }
  }
}

module.exports = {
  name: 'ember-segmentio',

  contentFor: function(type, config) {
    var content = '';
    var coreSnippet = readSnippet();
    var enabled = config.SEGMENTIO_KEY && coreSnippet;

    if (!config.SEGMENTIO_KEY) {
      console.warn('ember-segmentio: Not enabled missing key "SEGMENTIO_KEY" in parent application/addon.');
    }

    if (!coreSnippet) {
      console.warn('ember-segmentio: Error while reading snippet.');
    }

    if (enabled && type === 'head') {
      content = [
        '<script type="text/javascript">',
        '!function(){',
        coreSnippet,
        'analytics.load("', config.SEGMENTIO_KEY, '");',
        'analytics.page()',
        '}();',
        '</script>'
      ].join('');
    }
    return content;
  }

};

/* jshint node: true */
'use strict';

var fs = require('fs');
var path = require('path');

function readSnippet() {
  try {
    // NOTE: expecting addon as a node_module on parent addon or in an Ember CLI application.
    return fs.readFileSync(path.join(process.cwd(), 'node_modules/ember-segmentio/vendor/snippet-core.min.js'), {
      encoding: 'UTF-8'
    });
  } catch(error) {
    if (error.code === 'ENOENT') {
      return '';
    } else {
      throw error;
    }
  }
}

module.exports = {
  name: 'ember-segmentio',

  contentFor: function(type, config) {
    var content = '';
    var coreSnippet = readSnippet();
    var enabled = config.SEGMENTIO_KEY && coreSnippet;

    if (!config.SEGMENTIO_KEY) {
      console.warn('ember-segmentio: Not enabled missing key "SEGMENTIO_KEY" in parent application/addon.');
    }

    if (!coreSnippet) {
      console.warn('ember-segmentio: Error while reading snippet.');
    }

    if (enabled && type === 'head') {
      content = [
        '<script type="text/javascript">',
        '(function(){',
        coreSnippet,
        'analytics.load("', config.SEGMENTIO_KEY, '");',
        'analytics.page()',
        '})();',
        '</script>'
      ].join('');
    }
    return content;
  }

};

Add snippet fetching to HEAD


const markers = (state = {}, action) => {
  switch (action.type) {
    case 'ADD_MARKER':
      if (Array.isArray(action.newMarker)) {
        var allMarkers = {};
        action.newMarker.map((marker) => (
          allMarkers[marker._id] = marker
        ));
        return allMarkers;
      } else {
        return {
          ...state,
          [action.newMarker._id]: action.newMarker,
        };
      }
    default:
      return state;
  }
}

export default markers;

const markers = (state = {}, action) => {
  switch (action.type) {
    case 'ADD_MARKER':
      if (Array.isArray(action.newMarker)) {
        var allMarkers = {};
        action.newMarker.map((marker) => (
          allMarkers[marker.refId] = marker
        ));
        return allMarkers;
      } else {
        return {
          ...state,
          [action.newMarker.refId]: action.newMarker,
        };
      }
    default:
      return state;
  }
}

export default markers;

Change key of of stored boops with refId


'use strict'

const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectID;

module.exports = (mongodbUrl) => {

  async function getQuestionnaires() {
    // TODO: Mongodb-kutsu
    return new Promise(function(resolve, reject){
      setTimeout(function(){
        resolve("Hello World");
      }, 1000)
    });
  }
  async function putQuestionnaire(payload) {
    return new Promise(function(resolve, reject){
      let insertQuestionnaire = function(db, callback) {
        db.collection('questionnaires').insertOne(payload, function(err, result) {
          console.log("Inserted a questionnaire into the questionnaires collection.");
          callback();
        });
      };
      MongoClient.connect(mongodbUrl, function(err, db) {
        insertQuestionnaire(db, function() {
          db.close();
        });
      });
      resolve(payload.uuid);
    });
  }

  return {
    getQuestionnaires: getQuestionnaires,
    putQuestionnaire: putQuestionnaire
  };
}

'use strict'

const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectID;

module.exports = (mongodbUrl) => {

  async function getQuestionnaires() {
    // TODO: Mongodb-kutsu
    return new Promise(function(resolve, reject){
      setTimeout(function(){
        resolve("Hello World");
      }, 1000)
    });
  }
  async function putQuestionnaire(payload) {
    return new Promise(function(resolve, reject){
      let insertQuestionnaire = function(db, callback) {
        db.collection('questionnaires').insertOne(payload, function(err, result) {
          console.log("Inserted a questionnaire into the questionnaires collection.");
          callback();
        });
      };
      MongoClient.connect(mongodbUrl, function(err, db) {
        insertQuestionnaire(db, function() {
          db.close();
        });
      });

      let returnJson = new Object();
      returnJson.uuid = payload.uuid;
      returnJson.created = payload.created;
      returnJson.modified = payload.modified;
      resolve(JSON.stringify(returnJson));
    });
  }

  return {
    getQuestionnaires: getQuestionnaires,
    putQuestionnaire: putQuestionnaire
  };
}

Add return UUID,Created,Modified to putQuestionnaire


import React from 'react';
import Gravatar from 'react-gravatar';

const Footer = () => {
  const author = {
    name: 'Angelo Ocana',
    homeCity: 'Ottawa',
    email: 'angeloocana@gmail.com'
  };

  return (
    <Gravatar
      email={author.email}
      alt={author.name}
      width={60}
      height={60} />
    Written by {author.name} {' '}
    who lives and works in {author.homeCity} building really useful things.
  You should  follow him on Twitter

  );
};

export default Footer;

import React from 'react';
import Gravatar from 'react-gravatar';
import HeartIcon from 'react-icons/lib/fa/heart';
import GithubIcon from 'react-icons/lib/fa/github';
import Link from './Link';

const Footer = () => {
  const author = {
    name: 'Angelo Ocana',
    homeCity: 'Ottawa',
    email: 'angeloocana@gmail.com'
  };

  const blogGithubLink = 'https://github.com/angeloocana/angeloocana';

  return (<footer>
    <Gravatar
      email={author.email}
      alt={author.name}
      width={60}
      height={60} />
    Built with <HeartIcon /> by <Link to={author.defaultLink}>{author.name}</Link>
    <p>
      <Link to={blogGithubLink}><GithubIcon /> Do you want to see the source code? It's opensource, It's free, check it out!!!</Link>
    </p>
  </footer>
  );
};

export default Footer;

Add github link to footer


'use strict';

var walk = require('jade-walk');
var stringify = require('js-stringify');

module.exports = function addLoc (ast) {
  ast = JSON.parse(JSON.stringify(ast));
  walk(ast, function (node, replace) {
    if (node.type === 'Tag' || node.type === 'InterpolatedTag') {
      [
        { name: 'data-jade-file', val: node.filename, mustEscape: true },
        { name: 'data-jade-line', val: node.line, mustEscape: false },
        { name: 'data-jade-column', val: node.column, mustEscape: false }
      ].forEach(function (attr) {
        if (attr.val === undefined) return;
        var alreadyExisted = findAttr(node.attrs, attr.name);
        if (alreadyExisted) {
          alreadyExisted.val = stringify(attr.val);
          alreadyExisted.mustEscape = attr.mustEscape;
        } else {
          attr.val = stringify(attr.val);
          node.attrs.push(attr);
        }
      });
    }
  });
  return ast;
};

function findAttr (attrs, name) {
  for (var i = 0; i < attrs.length; i++) {
    if (attrs[i].name === name) return attrs[i];
  }
}

'use strict';

var walk = require('jade-walk');
var stringify = require('js-stringify');

module.exports = function (options) {
  return {
    preCodeGen: function (ast) {
      ast = JSON.parse(JSON.stringify(ast));
      walk(ast, function (node, replace) {
        if (node.type === 'Tag' || node.type === 'InterpolatedTag') {
          [
            { name: 'data-jade-file', val: node.filename, mustEscape: true },
            { name: 'data-jade-line', val: node.line, mustEscape: false },
            { name: 'data-jade-column', val: node.column, mustEscape: false }
          ].forEach(function (attr) {
            if (attr.val === undefined) return;
            var alreadyExisted = findAttr(node.attrs, attr.name);
            if (alreadyExisted) {
              alreadyExisted.val = stringify(attr.val);
              alreadyExisted.mustEscape = attr.mustEscape;
            } else {
              attr.val = stringify(attr.val);
              node.attrs.push(attr);
            }
          });
        }
      });
      return ast;
    }
  };
};

function findAttr (attrs, name) {
  for (var i = 0; i < attrs.length; i++) {
    if (attrs[i].name === name) return attrs[i];
  }
}

Rewrite using the latest Jade plugin architecture


/**
 * requestAnimationFrame polyfill v1.0.0
 * requires Date.now
 *
 * © Polyfiller 2015
 * Released under the MIT license
 * github.com/Polyfiller/requestAnimationFrame
 */
window.requestAnimationFrame || function (window) {

    'use strict';

    window.requestAnimationFrame = window.msRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.webkitRequestAnimationFrame
    || function () {

        var fps = 60;
        var delay = 1000 / fps;
        var animationStartTime = Date.now();
        var previousCallTime = animationStartTime;

        return function requestAnimationFrame(callback) {

            var requestTime = Date.now();
            var timeout = Math.max(0, delay - (requestTime - previousCallTime));
            var timeToCall = requestTime + timeout;

            previousCallTime = timeToCall;

            return window.setTimeout(function onAnimationFrame() {

                callback(timeToCall - animationStartTime);

            }, timeout);
        };
    }();

    window.cancelAnimationFrame = window.mozCancelAnimationFrame
    || window.webkitCancelAnimationFrame
    || window.cancelRequestAnimationFrame
    || window.msCancelRequestAnimationFrame
    || window.mozCancelRequestAnimationFrame
    || window.webkitCancelRequestAnimationFrame
    || function cancelAnimationFrame(id) {
           window.clearTimeout(id);
       };

}(this);

/**
 * requestAnimationFrame polyfill v1.0.0
 * requires Date.now
 *
 * © Polyfiller 2015
 * Released under the MIT license
 * github.com/Polyfiller/requestAnimationFrame
 */
window.requestAnimationFrame || function (window) {

    'use strict';

    window.requestAnimationFrame = window.msRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.webkitRequestAnimationFrame
    || function () {

        var fps = 60;
        var delay = 1000 / fps;
        var animationStartTime = Date.now();
        var previousCallTime = animationStartTime;

        return function requestAnimationFrame(callback) {

            var requestTime = Date.now();
            var timeout = Math.max(0, delay - (requestTime - previousCallTime));
            var timeToCall = requestTime + timeout;

            previousCallTime = timeToCall;

            return window.setTimeout(function onAnimationFrame() {

                callback(timeToCall - animationStartTime);

            }, timeout);
        };
    }();

    window.cancelAnimationFrame = window.mozCancelAnimationFrame
    || window.webkitCancelAnimationFrame
    || window.cancelRequestAnimationFrame
    || window.msCancelRequestAnimationFrame
    || window.mozCancelRequestAnimationFrame
    || window.webkitCancelRequestAnimationFrame
    || function cancelAnimationFrame(id) {
           window.clearTimeout(id);
       };

}(window);

Update IIFE to reference window directly


const DEFAULT_PERMITTED_POLICIES = 'none'
const ALLOWED_POLICIES = [
  'none',
  'master-only',
  'by-content-type',
  'all'
]

module.exports = function crossdomain (options) {
  options = options || {}

  let permittedPolicies
  if ('permittedPolicies' in options) {
    permittedPolicies = options.permittedPolicies
  } else {
    permittedPolicies = DEFAULT_PERMITTED_POLICIES
  }

  if (ALLOWED_POLICIES.indexOf(permittedPolicies) === -1) {
    throw new Error('"' + permittedPolicies + '" is not a valid permitted policy. Allowed values: ' + ALLOWED_POLICIES.join(', ') + '.')
  }

  return function crossdomain (req, res, next) {
    res.setHeader('X-Permitted-Cross-Domain-Policies', permittedPolicies)
    next()
  }
}

var DEFAULT_PERMITTED_POLICIES = 'none'
var ALLOWED_POLICIES = [
  'none',
  'master-only',
  'by-content-type',
  'all'
]

module.exports = function crossdomain (options) {
  options = options || {}

  var permittedPolicies
  if ('permittedPolicies' in options) {
    permittedPolicies = options.permittedPolicies
  } else {
    permittedPolicies = DEFAULT_PERMITTED_POLICIES
  }

  if (ALLOWED_POLICIES.indexOf(permittedPolicies) === -1) {
    throw new Error('"' + permittedPolicies + '" is not a valid permitted policy. Allowed values: ' + ALLOWED_POLICIES.join(', ') + '.')
  }

  return function crossdomain (req, res, next) {
    res.setHeader('X-Permitted-Cross-Domain-Policies', permittedPolicies)
    next()
  }
}

Use `var` in source code because Helmet supports Node 0.10


/*!
 * is-extglob <https://github.com/jonschlinkert/is-extglob>
 *
 * Copyright (c) 2014-2016, Jon Schlinkert.
 * Licensed under the MIT License.
 */

module.exports = function isExtglob(str) {
  if (typeof str !== 'string' || str === '') {
    return false;
  }

  var match;
  while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) {
    if (match[2]) return true;
    str = str.slice(match.index + match[0].length);
  }

  return false;
};

/*!
 * is-extglob <https://github.com/jonschlinkert/is-extglob>
 *
 * Copyright (c) 2014-2016, Jon Schlinkert.
 * Licensed under the MIT License.
 */

var regex = /(\\).|([@?!+*]\(.*\))/g;
module.exports = function isExtglob(str) {
  if (typeof str !== 'string' || str === '') {
    return false;
  }

  var match;
  while ((match = regex.exec(str))) {
    if (match[2]) return true;
    str = str.slice(match.index + match[0].length);
  }

  return false;
};

Move regex out of the function to improve RAM usage.


var explode = require('turf-explode');
var point = require('turf-point');

/**
 * Calculates the centroid of a polygon Feature or
 * FeatureCollection using the geometric mean of all vertices.
 * This lessens the effect of small islands and artifacts when calculating
 * the centroid of a set of polygons.
 *
 * @module turf/centroid
 * @param {FeatureCollection} fc a {@link Feature} or FeatureCollection of any type
 * @return {Point} a Point showing the centroid of the input feature(s)
 * @example
 * var poly = turf.polygon([[[0,0], [0,10], [10,10] , [10,0], [0, 0]]]);
 * var centroidPt = turf.centroid(poly);
 *
 * var result = turf.featurecollection([poly, centroidPt]);
 *
 * //=result
 */
module.exports = function(features){
  var vertices = explode(features).features,
    xSum = 0,
    ySum = 0,
    len = vertices.length;

  for (var i = 0; i < len; i++) {
    xSum += vertices[i].geometry.coordinates[0];
    ySum += vertices[i].geometry.coordinates[1];
  }

  return point(xSum / len, ySum / len);
};

var explode = require('turf-explode');
var point = require('turf-point');

/**
 * Calculates the centroid of a polygon Feature or
 * FeatureCollection using the geometric mean of all vertices.
 * This lessens the effect of small islands and artifacts when calculating
 * the centroid of a set of polygons.
 *
 * @module turf/centroid
 * @param {FeatureCollection} fc a {@link Feature} or FeatureCollection of any type
 * @return {Point} a Point showing the centroid of the input feature(s)
 * @example
 * var poly = turf.polygon([[
 * 	[105.818939,21.004714],
 * 	[105.818939,21.061754],
 * 	[105.890007,21.061754],
 * 	[105.890007,21.004714],
 * 	[105.818939,21.004714]
 * ]]);
 *
 * var centroidPt = turf.centroid(poly);
 *
 * var result = turf.featurecollection([poly, centroidPt]);
 *
 * //=result
 */
module.exports = function(features){
  var vertices = explode(features).features,
    xSum = 0,
    ySum = 0,
    len = vertices.length;

  for (var i = 0; i < len; i++) {
    xSum += vertices[i].geometry.coordinates[0];
    ySum += vertices[i].geometry.coordinates[1];
  }

  return point(xSum / len, ySum / len);
};

Change example from Null Island to Ha Noi


var express = require('express'),
    app     = express(),
    logger  = require('morgan'),
    stylus  = require('stylus');

app.use(logger());

// Stylus
app.use(
  stylus.middleware({
    src:     __dirname + '/assets',
    dest:    __dirname + '/public',
    compile: function (str, path, fn) {
      console.info('Compiling:', str, path)
      return stylus(str)
        .set('filename', path)
        .set('compress', true);
    }
  })
);

// Static files
app.use(express.static(__dirname + '/public'));

// app.get('/', function(req, res){
//   res.send('hello world');
// });

app.listen(3000);

var express = require('express'),
    app     = express(),
    logger  = require('morgan'),
    stylus  = require('stylus');

app.use(logger());

// Stylus
app.use(
  stylus.middleware({
    src:     __dirname + '/assets',
    dest:    __dirname + '/public',
    compile: function (str, path, fn) {
      console.info('Compiling:', str, path)
      return stylus(str)
        .set('filename', path)
        .set('compress', true);
    }
  })
);

// Static files
app.use(express.static(__dirname + '/public'));

app.listen(process.env.PORT || 3000);

Use the environment's port instead of 3000.


'use strict';

var es = require('event-stream');
var gutil = require('gulp-util');
var ejs = require('ejs');

module.exports = function (options, settings) {
    return es.map(function (file, cb) {
        try {
            settings = settings || {};
            if(!settings.ext) settings.ext = '.html';

            file.contents = new Buffer(ejs.render(file.contents.toString(), options));
            file.path = gutil.replaceExtension(file.path, settings.ext);
            cb(null, file);
        } catch (err) {
            return cb(new Error('gulp-ejs: ' + err));
        }
    });
};

'use strict';

var es = require('event-stream');
var gutil = require('gulp-util');
var ejs = require('ejs');

module.exports = function (options, settings) {
    settings = settings || {};
    settings.ext = settings.ext || '.html';

    return es.map(function (file, cb) {
        try {
            file.contents = new Buffer(ejs.render(file.contents.toString(), options));
            file.path = gutil.replaceExtension(file.path, settings.ext);
        } catch (err) {
            return cb(new gutil.PluginError('gulp-ejs', err));
        }
        cb(null, file);
    });
};

Change thrown error to gulputil.PluginError


/*
 * Copyright (c) 2012, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */

$(document).ready(function() {
  var body = document.querySelector('body');

  var loadScript = function (url) {
    var elt = document.createElement('script');
    elt.setAttribute('src', url);
    elt.setAttribute('async', 'async');
    body.appendChild(elt);
  };

  $.ajax({
    url: './pages.html',
    success: function (data) {
      $('body').append(data);
      loadScript('./js/main.js');
      loadScript('./js/help.js');
      loadScript('./js/license.js');
    }
  });
});

Add missing licence header to js file


var express = require("express");

var app = express();

app.use(express.static("dist"));

app.listen(3333);

var express = require("express");

var app = express();

app.use(express.static("dist"));

app.listen(process.env.port || 3333);

Allow port to be set by env vars


/**
 * Load Subject
 */
eval(require('fs').readFileSync('./src/RandomColor.js', 'utf8'));

/**
 * Test suite
 */
describe("RandomColor", function() {

    it("should exist", function() {
        var classy = new RandomColor(['whatevs']);
    });

});

/**
 * Load Subject
 */
eval(require('fs').readFileSync('./src/Utils.js', 'utf8'));
eval(require('fs').readFileSync('./src/RandomColor.js', 'utf8'));

/**
 * Test suite
 */
describe("RandomColor", function() {

    var samplePalette = ['#f00', '#ff0', '#fff'],
        subject;

    beforeEach(function() {
        subject = new RandomColor(samplePalette);
    });

    it("will be initialized with a given palette", function() {
        expect(subject._lastColor).toBe(false);
        expect(subject._delivered).toEqual([]);
        expect(subject._palette).toEqual(samplePalette);
    });

    it("will return different color on each call", function() {
        var color1 = subject.getColor(),
            color2 = subject.getColor(),
            color3 = subject.getColor();

        expect(color2).not.toEqual(color1);
        expect(color3).not.toEqual(color2);
    });

});

Add basic specs to the main functionality of getColor


'use strict';

const Promise = require('bluebird');
const rmdir = Promise.promisify(require('rimraf'));
const db = require('../shared/db');

module.exports = function() {
    getOldFolders().then(deleteFolders).done();
};

function getOldFolders() {
    return Promise.using(db(), function(client) {
        return client.queryAsync({
            name: 'get_old_folders',
            text: "select path from source_folder where created < ( now() - interval '24 hours' )",
            values: []
        }).get('rows');
    });
}

function deleteFolders(folders) {
    return deleteFolderEntries(folders).then(deleteFilesystemFolders);
}

function deleteFolderEntries(folders) {
    return folders.map(deleteFolderEntry);
}

function deleteFolderEntry(folder) {
    return Promise.using(db(), function(client) {
        return client.queryAsync({
            name: 'delete_folder',
            text: 'delete from source_folder where path = $1',
            values: [folder]
        });
    });
}

function deleteFilesystemFolders(folders) {
    return folders.map(rmdir);
}

'use strict';

const Promise = require('bluebird');
const rmdir = Promise.promisify(require('rimraf'));
const db = require('../shared/db');

module.exports = function() {
    getOldFolders().then(deleteFolders).done();
};

function getOldFolders() {
    return Promise.using(db(), function(client) {
        return client.queryAsync({
            name: 'get_old_folders',
            text: "select path from source_folder where created < ( now() - interval '24 hours' )",
            values: []
        }).get(0).get('rows');
    });
}

function deleteFolders(folders) {
    return deleteFolderEntries(folders).then(deleteFilesystemFolders);
}

function deleteFolderEntries(folders) {
    return Promise.map(folders, deleteFolderEntry);
}

function deleteFolderEntry(folder) {
    return Promise.using(db(), function(client) {
        return client.queryAsync({
            name: 'delete_folder',
            text: 'delete from source_folder where path = $1',
            values: [folder.path]
        });
    }).then(function() {
        return folder.path;
    });
}

function deleteFilesystemFolders(folders) {
    return folders.map(function(f) {
        rmdir(f, {});
    });
}

Fix the deleter that was never tested.


/* eslint-env node */
module.exports = {
    "framework": "qunit",
    "test_page": "tests/index.html?hidepassed",
    "disable_watching": true,
    "launch_in_ci": [
        "Chrome"
    ],
    "launch_in_dev": [
        "Chrome"
    ],
    "browser_args": {
        "Chrome": [
            "--headless",
            "--disable-gpu",
            "--remote-debugging-port=9222"
        ]
    }
};

/* eslint-env node */
module.exports = {
    "framework": "qunit",
    "test_page": "tests/index.html?hidepassed",
    "disable_watching": true,
    "launch_in_ci": [
        "Chrome"
    ],
    "launch_in_dev": [
        "Chrome"
    ],
    "browser_args": {
        "Chrome": [
            "--headless",
            "--disable-gpu",
            "--remote-debugging-port=9222",
            "--no-sandbox",
        ]
    }
};

Add --no-sandbox flag for testing in Jenkins


var removeExcessSpaces = function(htmlString) {
	var processedString = htmlString.replace(/\s+</g, '<');
	processedString = processedString.replace(/>\s+/g, '>');
  processedString = processedString.replace(/_/g, ' ');
	return processedString;
}

var ready = function(fn) {
  if(document.readyState != 'loading') {
    fn();
  }
  else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
ready(function() {
	document.querySelector('body').innerHTML = removeExcessSpaces(document.querySelector('body').innerHTML);

  new Controller();
});

var removeExcessSpaces = function(selector) {
  var htmlString = document.querySelector(selector).innerHTML;
	htmlString = htmlString.replace(/\s+</g, '<');
	htmlString = htmlString.replace(/>\s+/g, '>');
  htmlString = htmlString.replace(/_/g, ' ');
  document.querySelector(selector).innerHTML = htmlString;
}

var ready = function(fn) {
  if(document.readyState != 'loading') {
    fn();
  }
  else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
ready(function() {
  removeExcessSpaces('main');

  new Controller();
});

Update removeExcessSpaces to operate with side effects


// Auto-magically referenced. Yay.

$(document).ready(function() {
  var rubyFolders = gon.folders;
  if (!rubyFolders) {
      return;
  }

  var folders = {};
  var currentId = gon.currentFolder.id;

  // Convert all the folders to tree nodes.
  rubyFolders.forEach(function(folder) {
    var nameAndCount = folder.name + " (" + folder.count + ")";
    folders[folder.id] = {
      id: folder.id,
      label: nameAndCount,
      url: folder.url,
      parentId: folder.parent_folder_id,
      children: []
    };
  });

  var rootFolder;

  // Generate the tree we need for jqTree.
  for (var id in folders) {
    var folder = folders[id];
    var parentId = folder.parentId;
    if (!parentId) {
      rootFolder = folder;
    } else {
      folders[parentId].children.push(folder);
    }
  }
  var treeData = [rootFolder];

  // Set up the tree.
  var treeElement = $('#file-tree');
  treeElement.tree({
    data: treeData,
    autoOpen: true
  });

  // Select the folder we're currently in.
  var currentFolderNode = treeElement.tree('getNodeById', currentId);
  treeElement.tree('selectNode', currentFolderNode);

  // Set up bindings on the tree.
  treeElement.bind('tree.select', function(event) {
    var selectedNode = event.node;
    if (selectedNode) {
      var selectedFolderUrl = selectedNode.url;
      window.location.href = selectedFolderUrl;
    }
  });
});

// Auto-magically referenced. Yay.

$(document).ready(function() {
  var rubyFolders = gon.folders;
  if (!rubyFolders) {
      return;
  }

  var folders = {};
  var currentId = gon.currentFolder.id;

  // Convert all the folders to tree nodes.
  rubyFolders.forEach(function(folder) {
    var nameAndCount = folder.name + " (" + folder.count + ")";
    folders[folder.id] = {
      id: folder.id,
      label: nameAndCount,
      url: folder.url,
      parentId: folder.parent_folder_id,
      children: []
    };
  });

  var rootFolder;

  // Generate the tree we need for jqTree.
  for (var id in folders) {
    var folder = folders[id];
    var parentId = folder.parentId;
    if (!parentId) {
      rootFolder = folder;
    } else {
      folders[parentId].children.push(folder);
    }
  }
  var treeData = [rootFolder];

  // Set up the tree.
  var treeElement = $('#file-tree');
  treeElement.tree({
    data: treeData,
    autoOpen: true,
    keyboardSupport: false
  });

  // Select the folder we're currently in.
  var currentFolderNode = treeElement.tree('getNodeById', currentId);
  treeElement.tree('selectNode', currentFolderNode);

  // Set up bindings on the tree.
  treeElement.bind('tree.select', function(event) {
    var selectedNode = event.node;
    if (selectedNode) {
      var selectedFolderUrl = selectedNode.url;
      window.location.href = selectedFolderUrl;
    }
  });
});

Disable keyboard support on tree, so it doesn't trap scrolling.


const { countBy } = require('lodash');

/**
 * @param {Request[]} requests
 * @return {Object<string, number>}
 */
function countHits(requests) {
  return countBy(requests, (req) => {
    const headers = req.headers.response.join(' ').toLowerCase();
    if (headers.indexOf('x-cache') !== -1 && headers.indexOf('x-cache-hits') !== -1
      && headers.indexOf('x-served-by') !== -1) {
      return headers.indexOf('x-cache: hit') !== -1 ? 'hit' : 'miss';
    }
    return 'other';
  });
}

exports.countHits = countHits;

const { countBy } = require('lodash');

/**
 * @param {Request[]} requests
 * @return {Object<string, number>}
 */
function countHits(requests) {
  return countBy(requests, (req) => {
    const headers = req.headers;
    if (headers) {
      const resHeaders = headers.response.join(' ').toLowerCase();
      if (resHeaders.indexOf('x-cache') !== -1 && resHeaders.indexOf('x-cache-hits') !== -1
        && resHeaders.indexOf('x-served-by') !== -1) {
        return resHeaders.indexOf('x-cache: hit') !== -1 ? 'hit' : 'miss';
      }
    }
    return 'other';
  });
}

exports.countHits = countHits;

Fix calculation of cached requests


'use strict';

var Reporter = require('./lib/reporter');
var DependencyChecker = require('./lib/dependency-checker');

module.exports = function emberCliDependencyCheckerAddon(project) {
  var reporter = new Reporter();
  var dependencyChecker = new DependencyChecker(project, reporter);
  dependencyChecker.checkDependencies();

  return {
    name: 'ember-cli-dependency-checker'
  };
};

'use strict';

var Reporter = require('./lib/reporter');
var DependencyChecker = require('./lib/dependency-checker');

module.exports = {
  name: 'ember-cli-dependency-checker',
  init: function() {
    var reporter = new Reporter();
    var dependencyChecker = new DependencyChecker(this.project, reporter);
    dependencyChecker.checkDependencies();
  }
};

Use init instead of a bare constructor


const dotenv = require('dotenv-safe');
const fs = require('fs');
const DefinePlugin = require('webpack').DefinePlugin;

module.exports = DotenvPlugin;

function DotenvPlugin(options) {
  dotenv.config(options || {});
  this.example = dotenv.parse(fs.readFileSync('./.env.default'));
  this.env = dotenv.parse(fs.readFileSync('./.env'));
}

DotenvPlugin.prototype.apply = function(compiler) {
  const plugin = Object.keys(this.example).reduce((definitions, key) => {
    const existing = process.env[key];

    if (existing) {
      definitions[`process.env.${key}`] = JSON.stringify(existing);
      return definitions;
    }

    const value = this.env[key];
    if (value) definitions[`process.env.${key}`] = JSON.stringify(value);

    return definitions;
  }, {});

  compiler.apply(new DefinePlugin(plugin));
};

const dotenv = require('dotenv-safe');
const fs = require('fs');
const DefinePlugin = require('webpack').DefinePlugin;

module.exports = DotenvPlugin;

function DotenvPlugin(options) {
  dotenv.config(options || {});
  this.example = dotenv.parse(fs.readFileSync(options.sample));
  this.env = dotenv.parse(fs.readFileSync('./.env'));
}

DotenvPlugin.prototype.apply = function(compiler) {
  const plugin = Object.keys(this.example).reduce((definitions, key) => {
    const existing = process.env[key];

    if (existing) {
      definitions[`process.env.${key}`] = JSON.stringify(existing);
      return definitions;
    }

    const value = this.env[key];
    if (value) definitions[`process.env.${key}`] = JSON.stringify(value);

    return definitions;
  }, {});

  compiler.apply(new DefinePlugin(plugin));
};

Allow the sampled file to be passed in.


/*
 * Created brightSPARK Labs
 * www.brightsparklabs.com
 */

'use strict';

// -----------------------------------------------------------------------------
// MODULES
// -----------------------------------------------------------------------------

var es       = require('event-stream');
var execSync = require('execSync');
var gutil    = require('gulp-util');
var moment   = require('moment');

// -----------------------------------------------------------------------------
// EXPORTS
// -----------------------------------------------------------------------------

module.exports = function() {
    // format to pass to 'git log'
    var headerFormat = "\\newpage%n%n\
|**Document Control**|%n\
|-:|-%n\
|Last Modified On:|%cI%n\
|Last Modified By:|%cn%n\
|Generated On:| <%%= date %%>%n\
|Generated From:| <%%= file.relative %%>%n\
|Version Identifier:|%h%n\
%n\\newpage%n%n"

    var gitCommand = 'git --no-pager log -n1 --pretty=tformat:\'' +
                        headerFormat +'\'';

    return es.map(function(file, cb){
        var headerText = execSync.exec(gitCommand + ' ' + file.path).stdout;
        headerText = headerText || '';
        var data = {
            date : moment().utc().format(),
            file : file
        };
        file.contents = Buffer.concat([
            new Buffer(gutil.template(headerText, data)),
            file.contents
        ]);
        cb(null, file);
    });
};

Use pandoc's multiline_tables extension to build table


angular
  .module('app')
  .factory('history', function($window) {
    return {
      back: function() {
        $window.history.back();
      },
      forward: function() {
        $window.history.forward();
      }
    };
  })
  .directive('historyBack', function(history) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.on('click', function() {
          history.back();
        });
      }
    };
  })
  .directive('historyForward', function(history) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.on('click', function() {
          history.forward();
        });
      }
    };
  });

/**
* Service and directive to provide back / forward functioanlity in your app
* ----------------------------------------
* In addition we account for the user's initial app visit, when there is no "back"
* or back is another site (not this app). In these cases we send to the dashboard
*
* @note make more robust with default option setter for home
* @todo impliment similar for forward?
*
*/
angular
  .module('app')
  .factory('history', function($location, $window, $rootScope) {
    return {
      pageCount: 0,
      back: function() {
        if(this.pageCount > 1) {
            $window.history.back();
        } else {
            $location.url('/dashboard');
            $rootScope.$apply();
        }
      },
      forward: function() {
        $window.history.forward();
      }
    };
  })
  .run(function(history, $rootScope) {

      // keep track of our page count
      $rootScope.$on('$routseChangeSuccess', function() {
          history.pageCount++;
      });

  })
  .directive('historyBack', function(history) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.on('click', function() {
          history.back();
        });
      }
    };
  })
  .directive('historyForward', function(history) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.on('click', function() {
          history.forward();
        });
      }
    };
  });

Fix for instance where on initial app visit close button doesn't work.


function intersection(setA, setB) {
    return new Set([...setA].filter(x => setB.has(x)))
}

function uniqueArray(array) {
    function isItFirstOccurrence(element, index, array) {
	return index == array.indexOf(element)
    }
    return array.slice().filter(isItFirstOccurrence)
}

function sortByLengthDown(array) {
    return array.slice().sort((a, b) => b.length - a.length )
}

function removeFromArray(array, element) {
    const index = array.indexOf(element);

    if (index !== -1) {
        array.splice(index, 1);
    }
}

function intersection(setA, setB) {
    return new Set([...setA].filter(x => setB.has(x)))
}

function uniqueArray(array) {
    function isItFirstOccurrence(element, index, array) {
	return index == array.indexOf(element)
    }
    return array.slice().filter(isItFirstOccurrence)
}

function sortByLengthDown(array) {
    return array.slice().sort((a, b) => b.length - a.length )
}

function sortByLengthUp(array) {
    return array.slice().sort((a, b) => a.length - b.length )
}

function removeFromArray(array, element) {
    const index = array.indexOf(element);

    if (index !== -1) {
        array.splice(index, 1);
    }
}

Add sort by length up


var css = require('./css')
  , less = require('./less')
  , sass = require('./sass')
  , path = require('path')
  , writer = require('write-to-path')

module.exports = function (opts, cb) {
  if (typeof opts === 'string') opts = {entry: opts};
  if (typeof cb === 'string') opts.output = cb;

  if (opts.entry.substr(-4) === 'less') {
    less(opts, complete)
  } else if (opts.entry.substr(-4) === 'scss') {
    sass(opts, complete)
  } else {
    css(opts, complete)
  }

  function complete (err, src) {
    if (err) return cb(err)

    if (opts.transform) src = opts.transform(src)

    if (opts.output) {
      writer(path.resolve(process.cwd(), opts.output), {debug: opts.debug})(null, src)
    } else {
      cb(null, src)
    }
  }
}

var css = require('./css')
  , less = require('./less')
  , sass = require('./sass')
  , path = require('path')
  , writer = require('write-to-path')

module.exports = function (opts, cb) {
  if (typeof opts === 'string') opts = {entry: opts};
  if (typeof cb === 'string') opts.output = cb;

  if (opts.entry.substr(-4) === 'less') {
    less(opts, complete)
  } else if (opts.entry.substr(-4) === 'scss') {
    sass(opts, complete)
  } else {
    css(opts, complete)
  }

  function complete (err, src) {
    if (err && opts.output) throw err
    if (err) return cb(err)

    if (opts.transform) src = opts.transform(src)

    if (opts.output) {
      writer(path.resolve(process.cwd(), opts.output), {debug: opts.debug})(null, src)
    } else {
      cb(null, src)
    }
  }
}

Fix error handling when output file is specified


var chalk = require('chalk');

var redisStore;

var config = {
	secret: 'change-this-fool',
	resave: true,
	saveUninitialized: true
};

var redisConfig = {
	host: 'localhost',
	port: 6379
};

if(ENV === 'production') {
	var RedisStore = require('connect-redis')(require('express-session'));

	redisStore = new RedisStore(this.redis);

	redisStore.on('connect', function(){
		console.info("Redis connected succcessfully");
	});

	redisStore.on('disconnect', function(){
		console.error("[" + chalk.red('ERROR') + "]  Unable to connect to redis. Has it been started?");
		process.exit(2);
	});

	config.store = redisStore;
}

module.exports = config;

var chalk = require('chalk');

var redisStore;

var config = {
	secret: 'change-this-fool',
	resave: true,
	saveUninitialized: true
};

var redisConfig = {
	host: 'localhost',
	port: 6379
};

if(ENV === 'production') {
	var RedisStore = require('connect-redis')(require('express-session'));

	redisStore = new RedisStore(this.redis);

	redisStore.on('connect', function(){
		console.info("Redis connected succcessfully");
	});

	redisStore.on('disconnect', function(){
		throw new Error('Unable to connect to redis. Has it been started?');
	});

	config.store = redisStore;
}

module.exports = config;

Throw error (instead of log and exit) on redis connection failure.


// Storage
var tabs = {}

// Incoming request
chrome.extension.onRequest.addListener( function( request, sender, response ) {
	switch( request.action ) {

		// Bird spotted
		case 'twitterUser':

			// new tab, or tab changed URL
			if( tabs[ 't'+ sender.tab.id ] === undefined || tabs[ 't'+ sender.tab.id ].href != request.href ) {
				tabs[ 't'+ sender.tab.id ] = {
					users: {},
					amount: 0
				}
			}

			tabs[ 't'+ sender.tab.id ].users[ request.user.username.toLowerCase() ] = request.user
			tabs[ 't'+ sender.tab.id ].amount++
			tabs[ 't'+ sender.tab.id ].href = request.href

			// display icon
			chrome.pageAction.show( sender.tab.id )

			// all good
			response({ status: 'ok' })
			break;

		// Popup wants something
		case 'getUsers':
			response( tabs[ 't'+ request.tabId ] )
			break;

	}
})

// !Tab closed
chrome.tabs.onRemoved.addListener( function( tabId, removeInfo ) {
	if( tabs[ 't'+ tabId ] !== undefined ) {
		delete tabs[ 't'+ tabId ]
	}
})

Clean up memory on tab close


var debug       = require( 'debug' )( 'wpcom-vip' );
var request     = require( './lib/util/request' );

// Modules

function WPCOM_VIP( token ) {
    this.API_VERSION = '1';
    this.API_TIMEOUT = 10000;

    this.req = new Request( this );
}

WPCOM_VIP.prototype.req = new Request();

WPCOM_VIP.prototype.get = function() {
    return this.req.get.apply( arguments );
};

WPCOM_VIP.prototype.post = function() {
    return this.req.post.apply( arguments );
};

WPCOM_VIP.prototype.put = function() {
    return this.req.get.apply( arguments );
};

WPCOM_VIP.prototype.delete = function() {
    return this.req.delete.apply( arguments );
};

module.exports = WPCOM_VIP;

var debug       = require( 'debug' )( 'wpcom-vip' );
var request     = require( './lib/util/request' );

// Modules

function WPCOM_VIP( token ) {
    this.req = new Request( this );
}

WPCOM_VIP.prototype.API_VERSION = '1';
WPCOM_VIP.prototype.API_TIMEOUT = 10000;

WPCOM_VIP.prototype.req = new Request();

WPCOM_VIP.prototype.get = function() {
    return this.req.get.apply( arguments );
};

WPCOM_VIP.prototype.post = function() {
    return this.req.post.apply( arguments );
};

WPCOM_VIP.prototype.put = function() {
    return this.req.get.apply( arguments );
};

WPCOM_VIP.prototype.delete = function() {
    return this.req.delete.apply( arguments );
};

module.exports = WPCOM_VIP;

Make the version and timeout constants part of the prototype


(function() {
var top = window.top;

function passThroughClick(elem, messageKey) {
  elem.bind('click', function() {
    top.postMessage(messageKey, "*");
  });
}

window.addEventListener("message", function(messageObject) {
  var data = messageObject.data;

  if ( data === "highlight" ) {
    $('#highlight').prop('checked', true );
  } else if ( data === "auto_annotate" ) {
    $('#annotate_button').hide();
  } else if ( data === "annotate" ) {
    $('#annotate_button').addClass('active');
  } else if ( typeof data.title !== "undefined" ) {
    $('#title').val(data.title);
    $('#fact').val(data.text);
    $('#url').val(data.url);
  } else if ( data === "blacklist" ) {
    $('#highlight').prop('disabled', true);
    $('#annotate_button').prop('disabled', true);
  }
}, false);

passThroughClick( $('#slideUp, #slideDown'), "slideToggle");
passThroughClick( $('#annotate_button'), "annotateToggle");
passThroughClick( $('#highlight'), "highlightToggle");

$('#annotate_button').bind('click', function() {
  if ($(this).hasClass("active")) {
    $(this).removeClass("active");
  } else {
    $(this).addClass("active");
  }
});

})();

(function() {
var top = window.top;

function passThroughClick(elem, messageKey) {
  elem.bind('click', function() {
    top.postMessage(messageKey, "*");
  });
}

window.addEventListener("message", function(messageObject) {
  var data = messageObject.data;

  if ( data === "highlight" ) {
    $('#highlight').prop('checked', true );
  } else if ( data === "auto_annotate" ) {
    $('#annotate_button').css({'visibility': 'hidden'});
  } else if ( data === "annotate" ) {
    $('#annotate_button').addClass('active');
  } else if ( typeof data.title !== "undefined" ) {
    $('#title').val(data.title);
    $('#fact').val(data.text);
    $('#url').val(data.url);
  } else if ( data === "blacklist" ) {
    $('#highlight').prop('disabled', true);
    $('#annotate_button').prop('disabled', true);
  }
}, false);

passThroughClick( $('#slideUp, #slideDown'), "slideToggle");
passThroughClick( $('#annotate_button'), "annotateToggle");
passThroughClick( $('#highlight'), "highlightToggle");

$('#annotate_button').bind('click', function() {
  if ($(this).hasClass("active")) {
    $(this).removeClass("active");
  } else {
    $(this).addClass("active");
  }
});

})();

Annotate Button - Don't remove the element, but hide it so the layout stays intact


'use strict';
var cheerio = require('cheerio');
var he = require('he');
var hl = require('highlight.js');
var highlightAuto = hl.highlightAuto;
var highlight = hl.highlight;

module.exports = function(input) {
    this.cacheable();

    var $ = cheerio.load(input);

    $('code').replaceWith(function(i, e) {
        var $e = $(e);
        var text = $e.text();

        if(text.split('\n').length < 2) {
          return $('<code>' + he.encode(text) + '</code>');
        }

        var text = $e.text();
        var klass = $e.attr('class') || '';
        var lang = klass.split('lang-').filter(id);
        lang = lang && lang[0];

        if(lang) {
            return highlight(lang, text).value;
        }

        return highlightAuto(text).value;
    });

    $('pre').addClass('hljs');

    return $.html();
};

function id(a) {return a;}

'use strict';
var cheerio = require('cheerio');
var he = require('he');
var hl = require('highlight.js');
var highlightAuto = hl.highlightAuto;
var highlight = hl.highlight;

module.exports = function(input) {
    this.cacheable && this.cacheable();

    var $ = cheerio.load(input);

    $('code').replaceWith(function(i, e) {
        var $e = $(e);
        var text = $e.text();

        if(text.split('\n').length < 2) {
          return $('<code>' + he.encode(text) + '</code>');
        }

        var text = $e.text();
        var klass = $e.attr('class') || '';
        var lang = klass.split('lang-').filter(id);
        lang = lang && lang[0];

        if(lang) {
            return highlight(lang, text).value;
        }

        return highlightAuto(text).value;
    });

    $('pre').addClass('hljs');

    return $.html();
};

function id(a) {return a;}

Check against `this.cacheable` before running


function eval_clojure(code) {
    var data;
    $.ajax({
        url: "eval.json",
        data: { expr : code },
        async: false,
        success: function(res) { data = res; }
    });
    return data;
}

function html_escape(val) {
    var result = val;
    result = result.replace(/\n/g, "<br/>");
    result = result.replace(/[<]/g, "<");
    result = result.replace(/[>]/g, ">");
    return result;
}

function onValidate(input) {
    return (input != "");
}

function onHandle(line, report) {
    var input = $.trim(line);

    // perform evaluation
    var data = eval_clojure(input);

    // handle error
    if (data.error) {
        return [{msg: data.message, className: "jquery-console-message-error"}];
    }

    // display expr results
    return [{msg: data.result, className: "jquery-console-message-value"}];
}

var controller;

$(document).ready(function() {
    controller = $("#console").console({
        welcomeMessage:'',
        promptLabel: 'isla> ',
        commandValidate: onValidate,
        commandHandle: onHandle,
        autofocus:true,
        animateScroll:true,
        promptHistory:true
    });
});

function eval_clojure(code) {
    var data;
    $.ajax({
        url: "eval.json",
        data: { expr : code },
        async: false,
        success: function(res) { data = res; }
    });
    return data;
}

function html_escape(val) {
    var result = val;
    result = result.replace(/\n/g, "<br/>");
    result = result.replace(/[<]/g, "<");
    result = result.replace(/[>]/g, ">");
    return result;
}

function onValidate(input) {
    return (input != "");
}

function onHandle(line, report) {
    var input = $.trim(line);

    // perform evaluation
    var data = eval_clojure(input);

    // handle error
    if (data.error) {
        return [{msg: data.message, className: "jquery-console-message-error"}];
    }

    // display expr results
    return [{msg: data.result, className: "jquery-console-message-value"}];
}

var controller;

$(document).ready(function() {
    controller = $("#console").console({
        welcomeMessage:'',
        promptLabel: '> ',
        commandValidate: onValidate,
        commandHandle: onHandle,
        autofocus:true,
        animateScroll:true,
        promptHistory:true
    });
});

Change prompt to just '>'.


import React from "react";

class IntroWithButton extends React.Component {
  static displayName = "Panel.IntroWithButton";

  static propTypes = {
    children: React.PropTypes.node.isRequired
  };

  render() {
    let children = React.Children.toArray(this.props.children);

    let intro;
    let button;
    if(children.length == 1) {
      intro = children;
    } else {
      button = children.pop();
      intro = children;
    }

    if(button) {
      button = (

          {button}

      );
    }

    return (

        {intro}
        {button}

    );
  }
}

export default IntroWithButton;

Fix the flex on panels with buttons


$(function() {

    $('.dropdown').each(function() {
        var element = $(this);
        var dropdownList = element.find(".dropdownList");
        if(dropdownList.children().length === 0) {
            element.find("option").each(function(i, e) {
                $(e).addClass("opt-" + i);
                dropdownList.append($('
' + $(e).text() + '
'));
            });
        }
        var select = element.find("select").val();
        element.find(".dropdownValue").text(element.find('option[value="' + select + '"]').text())

    }).on('click', function() {
        var me = $(this);
        var list = me.find(".dropdownList");
        var opts = me.find(".hiddenDropdown");
        if(list.css("display") == "block") {
            list.hide();
        } else {
            $(".dropdownList").hide();
            list.show();
            list.find("li").one("click", function(event) {
                event.stopPropagation();
                list.hide().find("li").off("click");
                var me2 = $(this);
                var opt = me2.attr("class").replace("item", "opt");
                me.find(".dropdownValue").text(me2.text());
                opts.find("[selected=selected]").removeAttr("selected");
                var val = opts.find("." + opt).attr("selected", "selected").val();
                opts.val(val).trigger('change');
            })
        }

        $(document).one("click", function() {
            list.hide().find("li").off("mouseout").off("click");
        });
        return false;
    })
});

$(function() {
    $('.dropdown').each(function() {
        var me = $(this);
        var dropdownList = me.find(".dropdownList");
        if(dropdownList.children().length === 0) {
            me.find("option").each(function(i, e) {
                $(e).addClass("opt-" + i);
                dropdownList.append($('
' + $(e).text() + '
'));
            });
        }
        var select = me.find("select").val();
        me.find(".dropdownValue").text(me.find('option[value="' + select + '"]').text())
    });
    $(document).on("click", ".dropdown", function() {
        var me = $(this);
        var list = me.find(".dropdownList");
        var opts = me.find(".hiddenDropdown");
        if(list.css("display") == "block") {
            list.hide();
        } else {
            $(".dropdownList").hide();
            list.show();
            list.find("li").one("click", function(event) {
                event.stopPropagation();
                list.hide().find("li").off("click");
                var me2 = $(this);
                var opt = me2.attr("class").replace("item", "opt");
                me.find(".dropdownValue").text(me2.text());
                opts.find("[selected=selected]").removeAttr("selected");
                var val = opts.find("." + opt).attr("selected", "selected").val();
                opts.val(val).trigger('change');
            })
        }

        $(document).one("click", function() {
            list.hide().find("li").off("mouseout").off("click");
        });
        return false;
    });
});

Fix select element global listener


import ApolloClient, { createNetworkInterface } from 'apollo-client';

const client = new ApolloClient({
  networkInterface: createNetworkInterface({
    uri: '/graphql',
  }),
  queryDeduplication: true,
  reduxRootSelector: state => state.apollo,
});

export default function createApolloClient() {
  return client;
}

import ApolloClient, { createNetworkInterface } from 'apollo-client';

const client = new ApolloClient({
  networkInterface: createNetworkInterface({
    uri: '/graphql',
    opts: {
      credentials: 'include',
    },
  }),
  queryDeduplication: true,
  reduxRootSelector: state => state.apollo,
});

export default function createApolloClient() {
  return client;
}

Include credentials with Apollo request


function reverseArray(array) {
    let newArray = [];
    for (let i = array.length - 1; i >= 0; --i) {
        newArray.push(array[i]);
    }
    return newArray;
}

function reverseArrayInPlace(array) {
    for (let i = 0; i < Math.floor(array.length/2); ++i) {
        let temp = array[i];
        array[i] = array[array.length - 1 - i];
        array[array.length - 1 - i] = temp;
    }
}

function reverseArray(arr) {
	let revArr = [];
	for (let i = arr.length - 1; i >= 0; --i) {
		revArr.push(arr[i]);
	}

	return revArr;
}

function reverseArrayInPlace(arr) {
	for (let i = 0; i < Math.floor(arr.length / 2); ++i) {
		let upperIdx = arr.length - (1 + i);
		let temp = arr[i];
		arr[i] = arr[upperIdx];
		arr[upperIdx] = temp;
	}
}

Add chapter 4, exercise 2


//@flow

import styled, { css } from "styled-components";

export const Title = styled.h1`

  ${({ theme }: { theme: Theme }) => css`

    ${theme.type.title};
    font-size: ${theme.scale.s8()};
    color: ${theme.color.black};

    display: inline-block;
    text-align: center;
    line-height: 1;
    margin: 0;
    cursor: pointer;

  `}
`;

//@flow

import styled, { css } from "styled-components";

export const Title = styled.h1`

  ${({ theme }: { theme: Theme }) => css`

    ${theme.type.title};
    font-size: ${theme.scale.s3(2)};
    color: ${theme.color.black};
    z-index: 1;

    display: inline-block;
    text-align: center;
    line-height: 1;
    margin: 0;
    cursor: pointer;

  `}
`;

Adjust font-size of title and create new stacking context for Highlight


'use strict';

const statKeyTemplate = ctx => `windshaft.named-map-provider-cache.${ctx.metric}`;

module.exports = class NamedMapProviderReporter {
    constructor ({ namedMapProviderCache, intervalInMilliseconds } = {}) {
        this.namedMapProviderCache = namedMapProviderCache;
        this.intervalInMilliseconds = intervalInMilliseconds;
        this.intervalId = null;
    }

    start () {
        const { providerCache: cache } = this.namedMapProviderCache;
        const { statsClient: stats } = global;

        this.intervalId = setInterval(() => {
            stats.gauge(statKeyTemplate({ metric: 'named-map.count' }), cache.length);
            const providers = cache.dump();

            const namedMapInstantiations = providers.reduce((acc, { v: providers }) => {
                acc += Object.keys(providers).length;
                return acc;
            }, 0);

            stats.gauge(statKeyTemplate({ metric: 'named-map.instantiation.count' }), namedMapInstantiations);
        }, this.intervalInMilliseconds);
    }

    stop () {
        clearInterval(this.intervalId);
        this.intervalId = null;
    }
};

'use strict';

const statKeyTemplate = ctx => `windshaft.named-map-provider-cache.${ctx.metric}`;

module.exports = class NamedMapProviderReporter {
    constructor ({ namedMapProviderCache, intervalInMilliseconds } = {}) {
        this.namedMapProviderCache = namedMapProviderCache;
        this.intervalInMilliseconds = intervalInMilliseconds;
        this.intervalId = null;
    }

    start () {
        const { providerCache: cache } = this.namedMapProviderCache;
        const { statsClient: stats } = global;

        this.intervalId = setInterval(() => {
            const providers = cache.dump();
            stats.gauge(statKeyTemplate({ metric: 'named-map.count' }), providers.length);

            const namedMapInstantiations = providers.reduce((acc, { v: providers }) => {
                acc += Object.keys(providers).length;
                return acc;
            }, 0);

            stats.gauge(statKeyTemplate({ metric: 'named-map.instantiation.count' }), namedMapInstantiations);
        }, this.intervalInMilliseconds);
    }

    stop () {
        clearInterval(this.intervalId);
        this.intervalId = null;
    }
};

Fix stat named map providers cache count


import gulp from 'gulp';
import sourceMaps from 'gulp-sourcemaps';
import babel from 'gulp-babel';
import path from 'path';
import del from 'del';

const paths = {
  es6Path: './src/**/*.*',
  es6: [ './src/**/*.js', './src/**/*.json' ],
  es5: './dist',
  // Must be absolute or relative to source map
  sourceRoot: path.join( __dirname, 'src' )
};

gulp.task( 'clean:dist', () => {
  return del( [
    './dist/**/*'
  ] );
} );

gulp.task( 'build', [ 'clean:dist', 'copy:nonJs' ], () => {
  return gulp.src( paths.es6 )
    .pipe( sourceMaps.init() )
    .pipe( babel( {
      presets: [ 'es2015' ]
    } ) )
    .pipe( sourceMaps.write( '.', { sourceRoot: paths.sourceRoot } ) )
    .pipe( gulp.dest( paths.es5 ) );
} );

// Copy all the non JavaScript files to the ./dist folder
gulp.task( 'copy:nonJs', () => {

  return gulp.src( [ paths.es6Path, '!' + paths.es6 ] )
    .pipe( gulp.dest( paths.es5 ) )

} );

gulp.task( 'watch', [ 'build' ], () => {
  gulp.watch( paths.es6, [ 'build' ] );
} );

gulp.task( 'default', [ 'watch' ] );

import gulp from 'gulp';
import sourceMaps from 'gulp-sourcemaps';
import babel from 'gulp-babel';
import path from 'path';
import del from 'del';

const paths = {
  es6Path: './src/**/*.*',
  es6: [ './src/**/*.js', '!./src/**/*.json' ],
  es5: './dist',
  // Must be absolute or relative to source map
  sourceRoot: path.join( __dirname, 'src' )
};

gulp.task( 'clean:dist', () => {
  return del( [
    './dist/**/*'
  ] );
} );

gulp.task( 'build', [ 'clean:dist', 'copy:nonJs' ], () => {
  return gulp.src( paths.es6 )
    .pipe( sourceMaps.init() )
    .pipe( babel( {
      presets: [ 'es2015' ]
    } ) )
    .pipe( sourceMaps.write( '.', { sourceRoot: paths.sourceRoot } ) )
    .pipe( gulp.dest( paths.es5 ) );
} );

// Copy all the non JavaScript files to the ./dist folder
gulp.task( 'copy:nonJs', () => {

  return gulp.src( [ paths.es6Path, '!' + paths.es6 ] )
    .pipe( gulp.dest( paths.es5 ) )

} );

gulp.task( 'watch', [ 'build' ], () => {
  gulp.watch( paths.es6, [ 'build' ] );
} );

gulp.task( 'default', [ 'watch' ] );

Exclude .json files in the build


export default function createLocalStatePatch(state) {
  return {
    type: 'localState',
    value: state
  }
}

export default function createLocalStatePatch(state) {
  return {
    type: 'localState',
    value: state,
    local: true
  }
}

Add local: true on slate patches


import {testAndSnapshot} from 'lib/utils/component'
import BookmarkChooser from '../bookmark-chooser'

testAndSnapshot(BookmarkChooser)

import {testAndSnapshot} from 'lib/utils/component'
import BookmarkChooser from '../bookmark-chooser'

BookmarkChooser.name = 'BookmarkChooser'

testAndSnapshot(BookmarkChooser)

Set name for snapshot testing


'use strict';

// Polyfills for APIs which are not present on all supported
// versions of Chrome

// ES2015+ polyfills
require('core-js/fn/object/assign'); // Available: Chrome >= 45
require('core-js/fn/object/values'); // Available: Chrome issue #4663

// Polyfill for the fetch() API for Chrome < 42.
require('whatwg-fetch');

'use strict';

// Polyfills for APIs which are not present on all supported
// versions of Chrome

// ES2015+ polyfills
require('core-js/features/object/assign'); // Available: Chrome >= 45
require('core-js/features/object/values'); // Available: Chrome issue #4663

// Polyfill for the fetch() API for Chrome < 42.
require('whatwg-fetch');

Update core-js import paths for v3.0.0


var ffmpeg = require('../index');

var proc = ffmpeg('/path/to/your_movie.avi')
  // set the size of your thumbnails
  .size('150x100')
  // setup event handlers
  .on('end', function(files) {
    console.log('screenshots were saved as ' + files.join(', '));
  })
  .on('error', function(err) {
    console.log('an error happened: ' + err.message);
  })
  // take 2 screenshots at predefined timemarks
  .takeScreenshots({ count: 2, timemarks: [ '00:00:02.000', '6' ] }, '/path/to/thumbnail/folder');

var ffmpeg = require('../index');

var proc = ffmpeg('/path/to/your_movie.avi')
  // set the size of your thumbnails
  .size('150x100')
  // setup event handlers
  .on('filenames', function(filenames) {
    console.log('screenshots are ' + filenames.join(', '));
  })
  .on('end', function() {
    console.log('screenshots were saved);
  })
  .on('error', function(err) {
    console.log('an error happened: ' + err.message);
  })
  // take 2 screenshots at predefined timemarks
  .takeScreenshots({ count: 2, timemarks: [ '00:00:02.000', '6' ] }, '/path/to/thumbnail/folder');

Update thumbnail.js so as to not confuse people


module.exports = function(bot){
	bot.addCommand('help', 'Shows help', '<command>', USER_LEVEL_NORMAL, false, function(event){
		var message = '',
			prefix = bot.CommandManager.prefix;
			commands = bot.CommandManager.commands;
		if(event.params && event.params[0]){
			var name = event.params[0];
			if(commands && commands[name]){
				var command = commands[name];
				message += 'Usage: ' + (prefix + command.name) + ' ' + command.usage;
				message += '\nDescription: ' + command.description;
			}
		}else{
			message = 'Available commands: ';
			for(key in commands){
				var command = commands[key];
				if(bot.getLevel(event.source.host) >= command.level){
					message += (prefix + command.name) + ' ';
				}
			}
		}
		if(message){
			bot.message(event.target, message);
		}
	});
};

module.exports = function(bot){
	bot.addCommand('help', 'Shows help', '<command>', USER_LEVEL_NORMAL, false, function(event){
		var message = '',
			prefix = bot.CommandManager.prefix;
			commands = bot.CommandManager.commands;
		if(event.params && event.params[0]){
			var name = event.params[0];
			if(commands && commands[name]){
				var command = commands[name];
				message += 'Usage: ' + (prefix + command.name) + ' ' + command.usage;
				message += '\nDescription: ' + command.description;
			}
		}else{
			message = 'Available commands: ';
			for(key in commands){
				var command = commands[key];
				if(bot.getLevel(event.source.host) >= command.level && !command.hidden){
					message += (prefix + command.name) + ' ';
				}
			}
		}
		if(message){
			bot.message(event.target, message);
		}
	});
};

Hide commands that have been marked as hidden