(function($, document, window) {
    "use strict"

    window.animationHeartBeat = function (steps)
    {
        var max = steps;
        var delay = 70;
        var current = 0;
        var interval;
        var beat;

        $(document).bind('animation.stop', function()
        {
            console.log('animation.stop event caught');
            clearInterval(interval);
        });

        $(document).bind('animation.start', function()
        {
            console.log('animation.start event caught');

            if (current > max)
            {
                $(document).trigger('animation.reset');
            }

            interval = setInterval(beat, delay);
        });

        $(document).bind('animation.reset', function()
        {
            console.log('animation.reset event caught');

            current = 0;
        });

        beat = function ()
        {
            $(document).trigger('animation.beat', [{'current': current, 'max': max}]);
            current++;

            if (current > max)
            {
                $(document).trigger('animation.stop');
            }
        }
    }
})(jQuery, document, window);

(function($, document, window) {
    "use strict"

    window.animationHeartBeat = function (steps)
    {
        var max = steps;
        var delay = 70;
        var current = 0;
        var interval;
        var beat;

        $(document).bind('animation.stop', function()
        {
            console.log('animation.stop event caught');
            clearInterval(interval);
        });

        $(document).bind('animation.start', function()
        {
            console.log('animation.start event caught');

            if (current > max)
            {
                $(document).trigger('animation.reset');
            }

            interval = setInterval(beat, delay);
        });

        $(document).bind('animation.reset', function()
        {
            console.log('animation.reset event caught');

            current = 0;
        });

        $(document).bind('animation.beat', function(event, animation)
        {
            current = animation.current + 1;
        });

        beat = function ()
        {
            $(document).trigger('animation.beat', [{'current': current, 'max': max}]);

            if (current > max)
            {
                $(document).trigger('animation.stop');
            }
        }
    }
})(jQuery, document, window);

Allow current frame modifictation by event


Meteor.publish('channelPinnedMessages', function (search) {
  if (this.userId) {
    // TODO: checking if the user has access to these messages
    const channel = Channels.findOne({ $or: [{ _id: search }, { slug: search }] });
    return Messages.find({
      _id: {$in: channel.pinnedMessageIds}
    });
  }
  this.ready();
});

Meteor.publish('channelPinnedMessages', function (search) {
  if (this.userId) {
    // TODO: checking if the user has access to these messages
    const channel = Channels.findOne({ $or: [{ _id: search }, { slug: search }] });

    if (channel.pinnedMessageIds) {
      return Messages.find({
        _id: {$in: channel.pinnedMessageIds}
      });
    }
  }
  this.ready();
});

Fix subscription in error in channelPinnedMessages


import * as columnUtils from './columnUtils';
import * as compositionUtils from './compositionUtils';
import * as dataUtils from './dataUtils';
import * as rowUtils from './rowUtils';
import * as sortUtils from './sortUtils';

export default {
  columnUtils,
  compositionUtils,
  dataUtils,
  rowUtils,
  sortUtils,
};

import * as columnUtils from './columnUtils';
import * as compositionUtils from './compositionUtils';
import * as dataUtils from './dataUtils';
import * as rowUtils from './rowUtils';
import * as sortUtils from './sortUtils';
import { connect } from './griddleConnect';

export default {
  columnUtils,
  compositionUtils,
  dataUtils,
  rowUtils,
  sortUtils,
  connect,
};

Add connect to utils out


import { Component } from 'substance'
import CardComponent from '../shared/CardComponent'

export default class CollectionEditor extends Component {
  getActionHandlers () {
    return {
      'remove-item': this._removeCollectionItem
    }
  }

  render ($$) {
    const model = this.props.model
    let items = model.getItems()
    let el = $$('div').addClass('sc-collection-editor')
    items.forEach(item => {
      let ItemEditor = this._getItemComponentClass(item)
      el.append(
        $$(CardComponent).append(
          $$(ItemEditor, {
            model: item,
            // LEGACY
            // TODO: try to get rid of this
            node: item._node
          })
        )
      )
    })
    return el
  }

  _getItemComponentClass (item) {
    let ItemComponent = this.getComponent(item.type, true)
    if (!ItemComponent) {
      // try to find a component registered for a parent type
      if (item._node) {
        ItemComponent = this._getParentTypeComponent(item._node)
      }
    }
    return ItemComponent || this.getComponent('entity')
  }

  _getParentTypeComponent (node) {
    let superTypes = node.getSchema().getSuperTypes()
    for (let type of superTypes) {
      let NodeComponent = this.getComponent(type, true)
      if (NodeComponent) return NodeComponent
    }
  }

  _removeCollectionItem (item) {
    const model = this.props.model
    model.removeItem(item)
    // TODO: this is only necessary for fake collection models
    // i.e. models that are only virtual, which I'd like to avoid
    this.rerender()
  }
}

import { Component } from 'substance'
import CardComponent from '../shared/CardComponent'

export default class CollectionEditor extends Component {
  getActionHandlers () {
    return {
      'remove-item': this._removeCollectionItem
    }
  }

  render ($$) {
    const model = this.props.model
    let items = model.getItems()
    let el = $$('div').addClass('sc-collection-editor')
    items.forEach(item => {
      let ItemEditor = this._getItemComponentClass(item)
      el.append(
        $$(CardComponent).append(
          $$(ItemEditor, {
            model: item,
            // LEGACY
            // TODO: try to get rid of this
            node: item._node
          }).ref(item.id)
        )
      )
    })
    return el
  }

  _getItemComponentClass (item) {
    let ItemComponent = this.getComponent(item.type, true)
    if (!ItemComponent) {
      // try to find a component registered for a parent type
      if (item._node) {
        ItemComponent = this._getParentTypeComponent(item._node)
      }
    }
    return ItemComponent || this.getComponent('entity')
  }

  _getParentTypeComponent (node) {
    let superTypes = node.getSchema().getSuperTypes()
    for (let type of superTypes) {
      let NodeComponent = this.getComponent(type, true)
      if (NodeComponent) return NodeComponent
    }
  }

  _removeCollectionItem (item) {
    const model = this.props.model
    model.removeItem(item)
    // TODO: this is only necessary for fake collection models
    // i.e. models that are only virtual, which I'd like to avoid
    this.rerender()
  }
}

Put a ref for item editor.


// We should use `grunt-umd` instead of this explicit intro, but the tool does
// not camelize lib names containing '.' or '-', making the generated JS
// invalid; needs a pull request.
(function(mod) {
    // CommonJS, Node.js, browserify.
    if (typeof exports === "object" && typeof module === "object") {
        module.exports = mod(require('d3'),
                             require('d3.chart'),
                             require('d3.chart.base'),
                             requure('lodash'));
        return;
    }
    // AMD.
    if (typeof define === "function" && define.amd) {
        return define(['d3', 'd3.chart', 'd3.chart.base', 'lodash'], mod);
    }
    // Plain browser (no strict mode: `this === window`).
    this.d3ChartBubbleMatrix = mod(this.d3, this.d3Chart,
                                   this.d3ChartBase, this._);
})(function(d3, d3Chart, d3ChartBase, ld) {
  "use strict";
  var exports = {};

Add comment about explicit UMD


'use strict';
var chai = require('chai');
var supertest = require('supertest');
var api = supertest('https://apis-bank-dev.apigee.net'); // supertest init;

chai.should();

describe('/atms', function() {
  describe('get', function() {

    it('should respond with 200 OK', function(done) {
	  this.timeout(0);
      api.get('/apis/v1/locations/atms')
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        done();
      });
    });

  });

});

'use strict';
var chai = require('chai');
var supertest = require('supertest');
var api = supertest('https://apis-bank-dev.apigee.net'); // supertest init;

chai.should();

describe('/atms', function() {
  describe('get', function() {

    it('should respond with 200 OK', function(done) {
	  this.timeout(0);
      api.get('/apis/v1/locations/atms')
      .expect(400)
      .end(function(err, res) {
        if (err) return done(err);
        done();
      });
    });

  });

});

Change to check build pass in CI


'use strict'

module.exports = {
	// This function finds the minimum and maximum values in an array of numbers.
	findMinMax: function(numlist) {
		numlist.sort( function (a,b) {return a - b} );

		return [ numlist[0], numlist[numlist.length - 1] ];
	}
}

'use strict'

module.exports = {
	// This function finds the minimum and maximum values in an array of numbers.
	findMinMax: function(numlist) {
		numlist.sort( function (a,b) {return a - b} );

		if (numlist[0] == numlist[numlist.length - 1]) {
			return [numlist[0]];
		}
		else return [ numlist[0], numlist[numlist.length - 1] ];
	}
}

Implement functionality for equal min and max values.


/**
 * View for the room users list
 * @module views/pro/PlayHistoryView
 */
var panes = require('./panes');

var PlayHistoryView = Backbone.View.extend({

	id: "plugpro-play-history",
	className: "media-list history",

	initialize: function(){
		var JST = window.plugPro.JST;
		this.historyHTML = JST['play_history.html'];
	},

	render: function(){
		this.$el.html("");

		var historyList = API.getHistory();

		historyList.forEach( this.appendSong.bind(this) );
	},

	appendSong: function( songInfo ){

		var historyDiv = this.historyHTML( songInfo );

		this.$el.append( historyDiv );
	},

	destroy: function(){
		this.remove();
	},

	reposition: function(){
		var windowWidth = $(window).width();
		var windowHeight = $(window).height();

		var leftPosition = panes.get('userlist');
		var height = (windowHeight - 108) / 2;

		this.$el.css({
			"left": leftPosition + "px",
			"height": height + "px",
			"width": panes.get('middle')/2 + "px"
		});

		$('#vote').width( this.$el.outerWidth() );
		$('#vote').css({
			"left": 0
		});

	}

});

module.exports = PlayHistoryView;

/**
 * View for the room users list
 * @module views/pro/PlayHistoryView
 */
var panes = require('./panes');

var PlayHistoryView = Backbone.View.extend({

	id: "plugpro-play-history",
	className: "media-list history",

	initialize: function(){
		var JST = window.plugPro.JST;
		this.historyHTML = JST['play_history.html'];

		API.on( API.HISTORY_UPDATE, this.render.bind(this) );
	},

	render: function(){
		this.$el.html("");

		var historyList = API.getHistory();

		historyList.forEach( this.appendSong.bind(this) );
	},

	appendSong: function( songInfo ){

		var historyDiv = this.historyHTML( songInfo );

		this.$el.append( historyDiv );
	},

	destroy: function(){
		this.remove();
	},

	reposition: function(){
		var windowWidth = $(window).width();
		var windowHeight = $(window).height();

		var leftPosition = panes.get('userlist');
		var height = (windowHeight - 108) / 2;

		this.$el.css({
			"left": leftPosition + "px",
			"height": height + "px",
			"width": panes.get('middle')/2 + "px"
		});

		$('#vote').width( this.$el.outerWidth() );
		$('#vote').css({
			"left": 0
		});

	}

});

module.exports = PlayHistoryView;

Make play history stay up to date


import React, { Component } from 'react';

class MembersPreview extends Component {

  render() {
    const {displayName, image, intro, slug} = this.props;

    // TODO: remove inline styles and implement a system
    return (

            {displayName}

{intro}

    );
  }
}

MembersPreview.propTypes = {
  displayName: React.PropTypes.string.isRequired,
  image: React.PropTypes.shape({
    uri: React.PropTypes.string.isRequired,
    height: React.PropTypes.number,
    width: React.PropTypes.number,
  }),
  intro: React.PropTypes.string,
  slug: React.PropTypes.string.isRequired,
  usState: React.PropTypes.string,
};

export default MembersPreview;

Make image preview slightly wider for mockup


import {join} from "path"

import favicon from "koa-favicon"

// TODO: Rewrite this middleware from scratch because of synchronous favicon
//   reading.
const FAVICON_PATH = join(
  process.cwd(), "static/assets/img/icns/favicon/twi.ico"
)

const configureFavicon = () => favicon(FAVICON_PATH)

export default configureFavicon

// Based on koajs/favicon
import {resolve, join, isAbsolute} from "path"

import {readFile} from "promise-fs"

import invariant from "@octetstream/invariant"
import isPlainObject from "lodash/isPlainObject"
import isString from "lodash/isString"
import ms from "ms"

import getType from "core/helper/util/getType"

const ROOT = process.cwd()

const DEFAULT_PATH = join(ROOT, "static/assets/img/icns/favicon/twi.ico")

function favicon(path = DEFAULT_PATH, options = {}) {
  if (isPlainObject(path)) {
    [options, path] = [path, DEFAULT_PATH]
  }

  invariant(
    !isString(path), TypeError,
    "Path should be a string. Received %s", getType(path)
  )

  invariant(
    !isPlainObject(options), TypeError,
    "Options sohuld be a plain object. Received %s", getType(options)
  )

  if (!isAbsolute(path)) {
    path = resolve(ROOT, path)
  }

  const maxAge = ms(options.maxAge != null ? options.maxAge : "1d")

  const cacheControl = (
    `public, max-age=${maxAge < 1000 ? maxAge / 1000 : 0}`
  )

  let icon = null
  return async function faviconMiddleware(ctx, next) {
    if (ctx.path !== "/favicon.ico") {
      return await next()
    }

    if (ctx.method !== "GET" && ctx.method !== "HEAD") {
      ctx.status = ctx.method === "OPTIONS" ? 200 : 405
      ctx.set("Allow", "GET, HEAD, OPTIONS")
      return
    }

    if (!icon) {
      icon = await readFile(path)
    }

    ctx.set("Cache-Control", cacheControl)
    ctx.type = "image/x-icon"
    ctx.body = icon
  }
}

const configureFavicon = () => favicon()

export default configureFavicon

Rewrite favicon middleware from scratch.


describe('Test stuff', function () {
   it('should just work', function () {
       angular.mock.module('hdpuzzles');

       expect(true).toBe(true);
   });
});

describe('Test stuff', function () {
   it('should just work', function () {
       angular.mock.module('hdpuzzles');

       expect(true).toBe(false);
   });
});

Test if Travis CI reports a failure for failing unit tests.


import Leaflet from "leaflet";

import latlngType from "./types/latlng";
import PopupContainer from "./PopupContainer";

export default class Marker extends PopupContainer {
  componentWillMount() {
    super.componentWillMount();
    const {map, position, ...props} = this.props;
    this.leafletElement = Leaflet.marker(position, props);
  }

  componentDidUpdate(prevProps) {
    if (this.props.position !== prevProps.position) {
      this.leafletElement.setLatLng(this.props.position);
    }
  }
}

Marker.propTypes = {
  position: latlngType.isRequired
};

import Leaflet from "leaflet";

import latlngType from "./types/latlng";
import PopupContainer from "./PopupContainer";

export default class Marker extends PopupContainer {
  componentWillMount() {
    super.componentWillMount();
    const {map, position, ...props} = this.props;
    this.leafletElement = Leaflet.marker(position, props);
  }

  componentDidUpdate(prevProps) {
    if (this.props.position !== prevProps.position) {
      this.leafletElement.setLatLng(this.props.position);
    }

    if (this.props.icon !== prevProps.icon) {
      this.getLeafletElement().setIcon(this.props.icon);
    }
  }
}

Marker.propTypes = {
  position: latlngType.isRequired
};

Implement dynamic changing of marker icon


/*
 * CPU statistics
 */

var exec = require('child_process').exec;

/*
 * Unfortunately the majority of systems are en_US based, so we go with
 * the wrong spelling of 'utilisation' for the least hassle ;)
 */
function get_cpu_utilization(callback)
{
  switch (process.platform) {
  case 'linux':
    exec('mpstat -u -P ALL 1 1', function (err, stdout, stderr) {
      var capture = 0;
      stdout.split('\n').forEach(function (line) {
        var ret = {};
        if (line.length === 0) {
          capture = (capture) ? 0 : 1;
          return;
        }
        if (capture) {
          var vals = line.split(/\s+/);
          if (!vals[1].match(/\d+/)) {
            return;
          }
          ret['cpu.utilization.cpu' + vals[1] + '.user'] = vals[2];
          ret['cpu.utilization.cpu' + vals[1] + '.system'] = vals[4];
          ret['cpu.utilization.cpu' + vals[1] + '.iowait'] = vals[5];
          ret['cpu.utilization.cpu' + vals[1] + '.idle'] = vals[10];
          callback(ret);
        }
      });
    });
    break;
  }
}

module.exports.probes = {
  'cpu.utilization': get_cpu_utilization,
}

/*
 * CPU statistics
 */

var exec = require('child_process').exec;

/*
 * Unfortunately the majority of systems are en_US based, so we go with
 * the wrong spelling of 'utilisation' for the least hassle ;)
 */
function get_cpu_utilization(callback)
{
  switch (process.platform) {
  case 'linux':
    exec('mpstat -u -P ALL 1 1', function (err, stdout, stderr) {
      stdout.split('\n\n')[1].split('\n').forEach(function (line) {
        var ret = {};
        var vals = line.split(/\s+/);
        if (!vals[1].match(/\d+/)) {
          return;
        }
        ret['cpu.utilization.cpu' + vals[1] + '.user'] = vals[2];
        ret['cpu.utilization.cpu' + vals[1] + '.system'] = vals[4];
        ret['cpu.utilization.cpu' + vals[1] + '.iowait'] = vals[5];
        ret['cpu.utilization.cpu' + vals[1] + '.idle'] = vals[10];
        callback(ret);
      });
    });
    break;
  }
}

module.exports.probes = {
  'cpu.utilization': get_cpu_utilization,
}

Simplify things with better use of split().


/*global __WEBPACK_DEV_SERVER_DEBUG__*/
/*global __WEBPACK_DEV_SERVER_NO_FF__*/

let SAVE;

if (__WEBPACK_DEV_SERVER_DEBUG__) { // for webpack-dev-server auto simulate
  SAVE = require('./webpack-dev-server-util');

  if (!__WEBPACK_DEV_SERVER_NO_FF__) require('./webpack-dev-server-fetch');
}

window.SAVE2 = {
  VERSION: '2.0.1',
  lib: { view: SAVE },
  isCAT: () => window._EntityLibrary != null || window.location.hostname === 'save.github.io',
  simulate: () => {
    window.SAVE2.lib.view = require('./webpack-dev-server-util');
    require('./webpack-dev-server-fetch');
  },
};

/*global __WEBPACK_DEV_SERVER_DEBUG__*/
/*global __WEBPACK_DEV_SERVER_NO_FF__*/

let SAVE;
let host = window.location.hostname;

if (__WEBPACK_DEV_SERVER_DEBUG__) { // for webpack-dev-server auto simulate
  SAVE = require('./webpack-dev-server-util');

  if (!__WEBPACK_DEV_SERVER_NO_FF__) require('./webpack-dev-server-fetch');
}

window.SAVE2 = {
  VERSION: '2.0.1',
  lib: { view: SAVE },
  isCAT: () => window._EntityLibrary != null || host === 'sri-save.github.io' || host === '',
  simulate: () => {
    window.SAVE2.lib.view = require('./webpack-dev-server-util');
    require('./webpack-dev-server-fetch');
  },
};

Fix for host not being correct


// Stack grow safe implementation

'use strict';

var ensureValue = require('../../object/valid-value')
  , isArray     = Array.isArray;

module.exports = function () {
	var input = ensureValue(this), remaining, l, i, result = [];
	main: //jslint: ignore
	while (input) {
		l = input.length;
		for (i = 0; i < l; ++i) {
			if (isArray(input[i])) {
				if (i < (l - 1)) {
					if (!remaining) remaining = [];
					remaining.push(input.slice(i + 1));
				}
				input = input[i];
				continue main;
			}
			result.push(input[i]);
		}
		input = remaining ? remaining.pop() : null;
	}
	return result;
};

// Stack grow safe implementation

'use strict';

var ensureValue = require('../../object/valid-value')
  , isArray     = Array.isArray;

module.exports = function () {
	var input = ensureValue(this), index = 0, remaining, remainingIndexes, l, i, result = [];
	main: //jslint: ignore
	while (input) {
		l = input.length;
		for (i = index; i < l; ++i) {
			if (isArray(input[i])) {
				if (i < (l - 1)) {
					if (!remaining) {
						remaining = [];
						remainingIndexes = [];
					}
					remaining.push(input);
					remainingIndexes.push(i + 1);
				}
				input = input[i];
				index = 0;
				continue main;
			}
			result.push(input[i]);
		}
		if (remaining) {
			input = remaining.pop();
			index = remainingIndexes.pop();
		} else {
			input = null;
		}
	}
	return result;
};

Optimize to not use slice


import fs from 'fs'
import rc from 'rc'
import ini from 'ini'
import path from 'path'
import mkdirp from 'mkdirp'
import untildify from 'untildify'

const conf = rc('tickbin', {
  api: 'https://api.tickbin.com/',
  local: '~/.tickbin'
})

conf.local = untildify(conf.local)
conf.db = path.join(conf.local, 'data')

if (!fs.existsSync(conf.local)) {
  mkdirp.sync(conf.local)
}

function setConfig(key, value) {
  let parsed = {}
  let target = conf.config || untildify('~/.tickbinrc')
  if (conf.config) parsed = ini.parse(fs.readFileSync(target, 'utf-8'))
  parsed[key] = value
  fs.writeFileSync(target, ini.stringify(parsed))
}

export { setConfig }
export default conf

import fs from 'fs'
import rc from 'rc'
import ini from 'ini'
import path from 'path'
import mkdirp from 'mkdirp'
import untildify from 'untildify'

const conf = rc('tickbin', {
  api: 'https://api.tickbin.com/',
  local: '~/.tickbin'
})

conf.local = untildify(conf.local)
conf.db = path.join(conf.local, 'data')

if (!fs.existsSync(conf.local)) {
  mkdirp.sync(conf.local)
}

function storeUser(user) {
  storeKey('remote', user.couch.url)
  storeKey('user', user.id)
}

function storeKey(key, value) {
  let parsed = {}
  let target = conf.config || untildify('~/.tickbinrc')
  if (conf.config) parsed = ini.parse(fs.readFileSync(target, 'utf-8'))
  parsed[key] = value
  fs.writeFileSync(target, ini.stringify(parsed))
}

export { storeUser }
export default conf

Add a setUser function and change setConfig to setKey


export default {
    gameWidth: 1080,
    gameHeight: 1613,
    images: {
        'background-game': './assets/images/background-game.png',
        'background-landing': './assets/images/background-landing.png',
        'background-face': './assets/images/ui/background-face.png',
        'background-game-over': './assets/images/ui/background-face-game-over.png',
        'score-bar': './assets/images/ui/score-bar.png',
        frame: './assets/images/ui/frame.png',
        'food-bar': './assets/images/ui/food-bar.png',
        'drinks-bar': './assets/images/ui/drinks-bar.png',
        'black-background': './assets/images/ui/black-background.png',
        spit: './assets/images/player/spit.png'
    },
    rules: {
        drinkDecrementPerTimeUnit: 4,
        drinkDecrementTimeMilliSeconds: 1000,
        drinkMinimumAmount: -250,
        drinkMaximumAmount: 250,
        foodDecrementPerMove: 2,
        foodMinimumAmount: -250,
        foodMaximumAmount: 250,
        playerInitialMoveSpeed: 500,
        playerMaxDragMultiplier: 0.4,
        playerYPosition: 860,
        minimumSpawnTime: 1200,
        maximumSpawnTime: 2500,
    },
    gravity: 400,
    player: {
        mouthOffset: 180
    }
};

export default {
    gameWidth: 1080,
    gameHeight: 1613,
    images: {
        'background-game': './assets/images/background-game.png',
        'background-landing': './assets/images/background-landing.png',
        'background-face': './assets/images/ui/background-face.png',
        'background-game-over': './assets/images/ui/background-face-game-over.png',
        'score-bar': './assets/images/ui/score-bar.png',
        frame: './assets/images/ui/frame.png',
        'food-bar': './assets/images/ui/food-bar.png',
        'drinks-bar': './assets/images/ui/drinks-bar.png',
        'black-background': './assets/images/ui/black-background.png',
        spit: './assets/images/player/spit.png'
    },
    rules: {
        drinkDecrementPerTimeUnit: 2,
        drinkDecrementTimeMilliSeconds: 500,
        drinkMinimumAmount: -250,
        drinkMaximumAmount: 250,
        foodDecrementPerMove: 4,
        foodMinimumAmount: -250,
        foodMaximumAmount: 250,
        playerInitialMoveSpeed: 500,
        playerMaxDragMultiplier: 0.4,
        playerYPosition: 860,
        minimumSpawnTime: 1200,
        maximumSpawnTime: 2500,
    },
    gravity: 400,
    player: {
        mouthOffset: 180
    }
};

Tweak difficulty - adjust drink + food decrements


const request = require('supertest');
const app = require('../app');
describe('name to point', function () {
  it('should return JSON object with geolocation',
    function (done) {
      request(app)
        .get('/point?name=OldCity&lat=53.66&lon=23.83')
        .expect(200)
        .expect({
          lat: '53.70177645',
          lon: '23.8347894179425',
          display_name: 'OldCity, 17, улица Дубко, Девятовка, Ленинский район,' +
          ' Гродно, Гродненская область, 230012, Беларусь',
        })
        .end(function (err, res) {
          if (err) {
            return done(err);
          }
          done();
        });
    });
  it('should respond with Not Found in case of failed name resolution',
    function (done) {
      request(app)
        .get('/point?name=NONAME&lat=53.66&lon=23.83')
        .expect(404)
        .end(function (err, res) {
          if (err) {
            return done(err);
          }
          done();
        });
    });
});

const request = require('supertest');
const app = require('../app');
describe('name to point', function () {
  it('should return JSON object with geolocation',
    function (done) {
      request(app)
        .get('/point?name=OldCity&lat=53.66&lon=23.83')
        .expect(200)
        .expect({
          lat: '53.70177645',
          lon: '23.8347894179425',
          display_name: 'OldCity, 17, улица Дубко, Девятовка, Ленинский район,' +
          ' Гродно, Гродненская область, 230005, Беларусь',
        })
        .end(function (err, res) {
          if (err) {
            return done(err);
          }
          done();
        });
    });
  it('should respond with Not Found in case of failed name resolution',
    function (done) {
      request(app)
        .get('/point?name=NONAME&lat=53.66&lon=23.83')
        .expect(404)
        .end(function (err, res) {
          if (err) {
            return done(err);
          }
          done();
        });
    });
});

Write a correct postal address


const { downloadGalleryPhoto } = require("../../gallery-helpers");
const html = require("../../render-string");
const quality = 40;
const size = 300;

module.exports = class Gallery {
  data() {
    return {
      layout: "photography"
    };
  }

  async render({ collections }) {
    return html`

        ${collections.photo
          .filter(entry => entry.data.live)
          .sort((a, b) => new Date(b.data.date) - new Date(a.data.date))
          .map(async item => {
            const { file, page } = item.data;
            await downloadGalleryPhoto({ file, page });
            return html`

                <preview-img
                  src="${file}"
                  width="${size}"
                  height="${size}"
                  quality="${quality}"
                ></preview-img>

            `;
          })}

    `;
  }
};

const { downloadGalleryPhoto } = require("../../gallery-helpers");
const html = require("../../render-string");
const quality = 40;
const size = 300;

module.exports = class Gallery {
  data() {
    return {
      layout: "photography"
    };
  }

  async render({ collections }) {
    return html`

        ${collections.photo
          .filter(entry => entry.data.live)
          .sort((a, b) => new Date(b.data.date) - new Date(a.data.date))
          .map(async item => {
            const { file, page } = item.data;
            await downloadGalleryPhoto({ file, page });
            return html`

                <preview-img
                  src="${file}"
                  width="${size}"
                  height="${size}"
                  quality="${quality}"
                  loading="lazy"
                ></preview-img>

            `;
          })}

    `;
  }
};

Use lazy loading attribute on gallery


import React, { PropTypes, PureComponent } from 'react';
import { findDOMNode } from 'react-dom';
import { InputGroup } from 'binary-components';
import { isMobile } from 'binary-utils';
import { actions } from '../_store';
import MarketSubmarketPickerContainer from './MarketSubmarketPickerContainer';

export default class AssetPickerFilter extends PureComponent {

	static propTypes = {
		filter: PropTypes.object.isRequired,
	};

	componentDidMount() {
		const assetSearchNode = findDOMNode(this);
		if (!isMobile()) {
			setTimeout(() => assetSearchNode.firstChild.focus(), 300);
		}
	}

	onSearchQueryChange = e => {
		actions.updateAssetPickerSearchQuery(e.target.value);
	}

	onFilterChange = e => {
		actions.updateAssetPickerFilter(e);
	}

	render() {
		const { filter } = this.props;

		return (
			<div className="asset-picker-filter">
				<InputGroup
					className="asset-search"
					defaultValue={filter.query}
					type="search"
					placeholder="Search for assets"
					onChange={this.onSearchQueryChange}
				/>
				<MarketSubmarketPickerContainer
					onChange={this.onFilterChange}
					allOptionShown
					value={filter.filter}
				/>
			</div>
		);
	}
}

import React, { PropTypes, PureComponent } from 'react';
import { findDOMNode } from 'react-dom';
import { InputGroup } from 'binary-components';
import { isMobile } from 'binary-utils';
import { actions } from '../_store';
import MarketSubmarketPickerContainer from './MarketSubmarketPickerContainer';

export default class AssetPickerFilter extends PureComponent {

	static propTypes = {
		filter: PropTypes.object.isRequired,
	};

	componentDidMount() {
		const assetSearchNode = findDOMNode(this);
		if (!isMobile()) {
			setTimeout(() =>
				assetSearchNode.firstChild &&
				assetSearchNode.firstChild.firstChild &&
				assetSearchNode.firstChild.firstChild.focus(),
			100);
		}
	}

	onSearchQueryChange = e => {
		actions.updateAssetPickerSearchQuery(e.target.value);
	}

	onFilterChange = e => {
		actions.updateAssetPickerFilter(e);
	}

	render() {
		const { filter } = this.props;

		return (
			<div className="asset-picker-filter">
				<InputGroup
					className="asset-search"
					defaultValue={filter.query}
					type="search"
					placeholder="Search for assets"
					onChange={this.onSearchQueryChange}
				/>
				<MarketSubmarketPickerContainer
					onChange={this.onFilterChange}
					allOptionShown
					value={filter.filter}
				/>
			</div>
		);
	}
}

Fix asset picker input focus


$('.nav a').on('click', function(){
    $(".navbar-toggle").click();
});

$('.nav a').on('click', function(){
    if ($(window).width() <= 767) {
        $(".navbar-toggle").click();
    }
});

Hide close animation for non mobile.


/**
 * @requires Map.js
 * @requires ArrayList.js
 */

/**
 * @see http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
 *
 * @implements {javascript.util.Map}
 * @constructor
 * @export
 */
javascript.util.HashMap = function() {
  this.object = {};
};

/**
 * @type {Object}
 * @private
 */
javascript.util.HashMap.prototype.object = null;

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.get = function(key) {
  return this.object[key];
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.put = function(key, value) {
  this.object[key] = value;
  return value;
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.values = function() {
  var arrayList = new javascript.util.ArrayList();
  for ( var key in this.object) {
    if (this.object.hasOwnProperty(key)) {
      arrayList.add(this.object[key]);
    }
  }
  return arrayList;
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.size = function() {
  return this.values().size();
};

/**
 * @requires Map.js
 * @requires ArrayList.js
 */

/**
 * @see http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
 *
 * @implements {javascript.util.Map}
 * @constructor
 * @export
 */
javascript.util.HashMap = function() {
  this.object = {};
};

/**
 * @type {Object}
 * @private
 */
javascript.util.HashMap.prototype.object = null;

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.get = function(key) {
  return this.object[key] || null;
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.put = function(key, value) {
  this.object[key] = value;
  return value;
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.values = function() {
  var arrayList = new javascript.util.ArrayList();
  for ( var key in this.object) {
    if (this.object.hasOwnProperty(key)) {
      arrayList.add(this.object[key]);
    }
  }
  return arrayList;
};

/**
 * @override
 * @export
 */
javascript.util.HashMap.prototype.size = function() {
  return this.values().size();
};

Fix so that get returns null instead of undefined when key not found.


/**
 * [schema defines validation schemas for Mongo documents being inserted into db:ibu collection:ibuerrors]
 *
 *
 */

var ibuErrorSchema = new Schema({
  filename: {
    type: String,
    validate: {
      validator: function(v){
        return /^[^.]+$/.test(v);
      },
      message: 'Filename is not valid!'
    }
  },
  collection: {
    type: String
  },
  IMGerrors: {
    type: Array
  },
  XMLerrors: {
    type: Array
  }
});

var ibuErrorDoc = mongoose.model('ibuErrorDoc', ibuErrorSchema);

'use strict';
/**
 * [schema defines validation schemas for Mongo documents being inserted into db:ibu collection:ibuerrors]
 *
 *
 */
 // Mongoose connection to MongoDB
const mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ibuErrorSchema = new Schema({
  filename: {
    type: String,
    trim: true
  },
  filePathXML: {
    type: String,
    unique: true
  },
  filePathIMG: {
    type: String,
    unique: true
  },
  extentionName: {
    type: String,
    trim: true
  },
  libCollection: {
    type: String
  },
  IMGerrors: {
    type: Array
  },
  XMLerrors: {
    type: Array
  },
  created: {
    type: Date , default: Date.now
  }
});
//,
// validate: {
//   validator: function(v){
//     return /^[^.]+$/.test(v);

var ibuErrorDoc = mongoose.model('ibuErrorDoc', ibuErrorSchema);
module.exports = ibuErrorDoc;

Add Fields & removed Validate


define(['app'], function (app) {
  "use strict";

  return app.service('storageService', ['$window', function (win) {
      this.available = 'localStorage' in win;

      this.get = function (key) {
        return win.localStorage.getItem(key);
      };

      this.set = function (key, value) {
        return win.localStorage.setItem(key, value);
      };

      this.setJSON = function (key, value) {
        return this.set(key, win.JSON.stringify(value));
      };

      this.getJSON = function (key) {
        return win.JSON.parse(this.get(key));
      };
  }]);
});

define(['app', 'angular'], function (app, angular) {
  "use strict";

  return app.service('storageService', ['$window', function (win) {
      this.available = 'localStorage' in win;

      this.get = function (key) {
        return win.localStorage.getItem(key);
      };

      this.set = function (key, value) {
        return win.localStorage.setItem(key, value);
      };

      this.setJSON = function (key, value) {
        return this.set(key, angular.toJson(value));
      };

      this.getJSON = function (key) {
        return angular.fromJson(this.get(key));
      };
  }]);
});

Use angular's JSON lib, since it strips off $hashKey that angular adds to scope objects


'use babel'

import {getPath} from 'consistent-path'
export {tempFile} from 'atom-linter'

const assign = Object.assign || function(target, source) {
    for (const key in source) {
      target[key] = source[key]
    }
    return target
  }

export function getEnv() {
  const env = assign({}, process.env)
  env.PATH = getPath()
  return env
}

'use babel'

import getEnvironment from 'consistent-env'
export {tempFile} from 'atom-linter'

const assign = Object.assign || function(target, source) {
    for (const key in source) {
      target[key] = source[key]
    }
    return target
  }

export function getEnv() {
  return getEnvironment()
}

Use consistent-env instead of consistent-path


import { Dimensions } from 'react-native'

module.exports = {
  get visibleHeight() {
    return Dimensions.get('window').height
  },
}

import { Dimensions } from 'react-native'

module.exports = {
  get visibleHeight() {
    return Dimensions.get('screen').height
  },
}

Use screen dimension as visible height


'use strict';

const { protocolHandlers } = require('../../protocols');
const { rpcHandlers } = require('../../rpc');

// Build message of events of type `request` as:
//  STATUS [ERROR] - PROTOCOL METHOD RPC /PATH COMMAND...
const getRequestMessage = function ({
  protocol,
  rpc,
  method,
  path,
  error = 'SUCCESS',
  commandpath,
  summary,
}) {
  const summaryA = error ? commandpath : summary;

  const { title: protocolTitle } = protocolHandlers[protocol] || {};
  const { title: rpcTitle } = rpcHandlers[rpc] || {};

  const message = [
    error,
    '-',
    protocolTitle,
    method,
    rpcTitle,
    path,
    summaryA,
  ].filter(val => val)
    .join(' ');
  return message;
};

module.exports = {
  getRequestMessage,
};

'use strict';

const { protocolHandlers } = require('../../protocols');
const { rpcHandlers } = require('../../rpc');

// Build message of events of type `request` as:
//  STATUS [ERROR] - PROTOCOL METHOD RPC /PATH COMMAND...
const getRequestMessage = function ({
  protocol,
  rpc,
  method,
  path,
  error = 'SUCCESS',
  commandpath,
  summary,
}) {
  const summaryA = error === 'SUCCESS' ? summary : commandpath;

  const { title: protocolTitle } = protocolHandlers[protocol] || {};
  const { title: rpcTitle } = rpcHandlers[rpc] || {};

  const message = [
    error,
    '-',
    protocolTitle,
    method,
    rpcTitle,
    path,
    summaryA,
  ].filter(val => val)
    .join(' ');
  return message;
};

module.exports = {
  getRequestMessage,
};

Fix summary not showing up in console logs


var fs = require('fs');

function getInitialCharge() {
  var initialCharge = 100,
      body = fs.readFileSync('tesla.out').toString().split('\n');

  for (var i = body.length - 1; i >= 0; i--) { // Pick out valid part of file.
    if (body[i].indexOf('battery_level:') != -1) { // Pick out the last object.
      initialCharge = +(body[i].split(':')[1].slice(0, -1));
      console.log(initialCharge);
      return initialCharge;
    }
  }
  return initialCharge;
}

exports.getInitialCharge = getInitialCharge;

var fs = require('fs');

function getInitialCharge() {
  var initialCharge = 100,
      body = fs.readFileSync('tesla.out').toString().split('\n');

  for (var i = body.length - 1; i >= 0; i--) { // Pick out valid part of file.
    if (body[i].indexOf('battery_level:') != -1) { // Pick out the last object.
      initialCharge = +(body[i].split(':')[1].slice(0, -1));
      console.log(initialCharge);
      return initialCharge;
    }
  }
  return initialCharge;
}

if (require.main === module) {
  getInitialCharge();
}
exports.getInitialCharge = getInitialCharge;

Check if called from command line.


import test from 'ava';
import Canvas from 'canvas';
import mergeImages from '../';
import fixtures from './fixtures';

test('mergeImages rejects Promise if image load errors', async t => {
	t.plan(1);
	t.throws(mergeImages([1], { Canvas }));
});

import test from 'ava';
import Canvas from 'canvas';
import mergeImages from '../';
import fixtures from './fixtures';

test('mergeImages rejects Promise if node-canvas instance isn\'t passed in', async t => {
	t.plan(1);
	t.throws(mergeImages([]));
});

test('mergeImages rejects Promise if image load errors', async t => {
	t.plan(1);
	t.throws(mergeImages([1], { Canvas }));
});

Test mergeImages rejects Promise if node-canvas instance isn\'t passed in


'use strict';
/*global describe */

describe('Issues.', function () {
  require('./issues/issue-8.js');
  require('./issues/issue-17.js');
  require('./issues/issue-19.js');
  require('./issues/issue-26.js');
  require('./issues/issue-33.js');
  require('./issues/issue-46.js');
  require('./issues/issue-54.js');
  require('./issues/issue-64.js');
  require('./issues/issue-85.js');
  require('./issues/issue-92.js');
  require('./issues/issue-93.js');
  require('./issues/issue-95.js');
  require('./issues/issue-parse-function-security.js');
  require('./issues/issue-skip-invalid.js');
});

'use strict';
/*global describe */

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

describe('Issues.', function () {
  var issues = path.resolve(__dirname, 'issues');

  fs.readdirSync(issues).forEach(function (file) {
    if ('.js' === path.extname(file)) {
      require(path.resolve(issues, file));
    }
  });
});

Automate loading of issue test units.


var cp = require('child_process');
var walk = require('walk');

var walker = walk.walk(__dirname + '/spec', {followLinks: false});
walker.on('file', function(root, stat, next) {

  var filepath = root + '/' + stat.name;
  cp.fork('node_modules/mocha/bin/_mocha', [filepath]);

  next();
});

var cp = require('child_process');
var join = require('path').join;
var walk = require('walk');
var mochaBin = join(__dirname, '..', 'node_modules', '.bin', 'mocha');

var walker = walk.walk(__dirname + '/spec', {followLinks: false});
walker.on('file', function(root, stat, next) {
  var filepath = root + '/' + stat.name;
  cp.spawn(mochaBin, [filepath], {stdio: 'inherit'});

  next();
});

Replace child_process.fork with child_process.spawn to correctly handle child's output.


'use strict'

const fs = require('fs')
const gulp = require('gulp')
const lessModule = require('less')
const less = require('gulp-less')
const sourcemaps = require('gulp-sourcemaps')
const rename = require('gulp-rename')
const mkdirp = require('mkdirp')

const postcss = require('gulp-postcss')
const autoprefixer = require('autoprefixer')

const config = require('../config').less

const errorHandler = require('../util/error-handler')

lessModule.functions.functionRegistry.addMultiple(config.functions)

const processors = [
  autoprefixer(),
]

if (process.env.NODE_ENV === 'production') {
  const csswring = require('csswring')

  processors.push(csswring())
}

gulp.task('less', () => {
  mkdirp.sync(config.dest)

  if (config.suffix) {
    fs.writeFile(`${config.dest}.json`, JSON.stringify({ suffix: config.suffix }))
  }

  let pipe = gulp.src(config.src)
    .pipe(sourcemaps.init())
    .pipe(less(config.options).on('error', errorHandler))
    .pipe(postcss(processors))

  if (config.suffix) {
    pipe = pipe.pipe(rename({ suffix: config.suffix }))
  }

  return pipe.pipe(sourcemaps.write('./maps'))
    // .on('error', errorHandler)
    .pipe(gulp.dest(config.dest))
})

'use strict'

const fs = require('fs')
const gulp = require('gulp')
const lessModule = require('less')
const less = require('gulp-less')
const sourcemaps = require('gulp-sourcemaps')
const rename = require('gulp-rename')
const mkdirp = require('mkdirp')

const postcss = require('gulp-postcss')
const autoprefixer = require('autoprefixer')

const config = require('../config').less

const errorHandler = require('../util/error-handler')

lessModule.functions.functionRegistry.addMultiple(config.functions)

const processors = [
  autoprefixer(),
]

if (process.env.NODE_ENV === 'production') {
  const csswring = require('csswring')

  processors.push(csswring())
}

gulp.task('less', () => {
  mkdirp.sync(config.dest)

  if (config.suffix) {
    fs.writeFileSync(`${config.dest}.json`, JSON.stringify({ suffix: config.suffix }))
  }

  let pipe = gulp.src(config.src)
    .pipe(sourcemaps.init())
    .pipe(less(config.options).on('error', errorHandler))
    .pipe(postcss(processors))

  if (config.suffix) {
    pipe = pipe.pipe(rename({ suffix: config.suffix }))
  }

  return pipe.pipe(sourcemaps.write('./maps'))
    // .on('error', errorHandler)
    .pipe(gulp.dest(config.dest))
})

Use sync fs method (to suppress no callback error)


module.exports = function(syno) {
  return {
  };
};

'use strict';

var util = require('util');

function info() {
  /*jshint validthis:true */
  var
    userParams =
      typeof arguments[0] === 'object' ? arguments[0] :
      {},
    callback =
      typeof arguments[1] === 'function' ? arguments[1] :
      typeof arguments[0] === 'function' ? arguments[0] :
      null
  ;
  var params = {
    api    : 'SYNO.DownloadStation.Info',
    version: 1,
    method : 'getinfo'
  };
  util._extend(params, userParams);

  var query = this.query({
    path: '/webapi/DownloadStation/info.cgi',
    params: params
  }, callback || null);

  return query;
}

function getConfig() {
  /*jshint validthis:true */
  var
    userParams =
      typeof arguments[0] === 'object' ? arguments[0] :
      {},
    callback =
      typeof arguments[1] === 'function' ? arguments[1] :
      typeof arguments[0] === 'function' ? arguments[0] :
      null
  ;
  var params = {
    api    : 'SYNO.DownloadStation.Info',
    version: 1,
    method : 'getconfig'
  };
  util._extend(params, userParams);

  var query = this.query({
    path: '/webapi/DownloadStation/info.cgi',
    params: params
  }, callback || null);

  return query;
}

function setConfig() {
  /*jshint validthis:true */
  var
    userParams =
      typeof arguments[0] === 'object' ? arguments[0] :
      {},
    callback =
      typeof arguments[1] === 'function' ? arguments[1] :
      typeof arguments[0] === 'function' ? arguments[0] :
      null
  ;
  var params = {
    api    : 'SYNO.DownloadStation.Info',
    version: 1,
    method : 'setserverconfig'
  };
  util._extend(params, userParams);

  var query = this.query({
    path: '/webapi/DownloadStation/info.cgi',
    params: params
  }, callback || null);

  return query;
}

module.exports = function(syno) {
  return {
    info     : info.bind(syno),
    getConfig: getConfig.bind(syno),
    setConfig: setConfig.bind(syno)
  };
};

Add Synology.downloadStation.info, Synology.downloadStation.getConfig and Synology.downloadStation.setConfig


/*
 * Find scopes from AST
 * @lastmodifiedBy ChengFuLin(chengfulin0806@gmail.com)
 * @lastmodifiedDate 2015-07-27
 */
var walkes = require('walkes');

/**
 * ScopeFinder
 * @constructor
 */
function ScopeFinder() {
}

/**
 * Find function scopes of AST parsed from source
 * @param {Object} ast JS parsed AST
 * @returns {Object} Array of ASTs, each corresponds to global or function scope
 */
ScopeFinder.prototype.findScopes = function (ast) {
	'use strict';
	var scopes = [];
	function handleInnerFunction(astNode, recurse) {
		scopes.push(astNode);
		recurse(astNode.body);
	}

	walkes(ast, {
		Program: function (node, recurse) {
			scopes.push(node);
			node.body.forEach(function (elem) {
				recurse(elem);
			});
		},
		FunctionDeclaration: handleInnerFunction,
		FunctionExpression: handleInnerFunction
	});
	return scopes;
};

var finder = new ScopeFinder();
module.exports = finder;

Modify default line separator from CRLF to LF


global.XMLHttpRequest = require('xhr2');
global.dataLayer = [];
var test = require('blue-tape');
var GeordiClient = require('../index');

test('Instantiate a client with default settings', function(t) {
  var geordi = new GeordiClient();
  t.equal(geordi.env, 'staging');
  t.equal(geordi.projectToken, 'unspecified');
  t.end()
});
test('Log without a valid project token', function(t) {
  var geordi = new GeordiClient({projectToken:''});
  geordi.logEvent('test event')
    .then(function(response){
      t.fail('invalid project token should not be logged');
      t.end()
    })
    .catch(function(error){
      t.pass(error);
      t.end()
    });
});
test('Log with valid project token', function(t) {
  var geordi = new GeordiClient({projectToken: 'test/token'});
  geordi.logEvent('test event')
    .then(function(response){
      t.pass('Valid project token will allow logging');
      t.end()
    })
});
test('Update data on Geordi', function(t) {
  var geordi = new GeordiClient({projectToken: 'test/token'});
  geordi.update({projectToken: 'new/token'})
  t.equal(geordi.projectToken, 'new/token');
  t.end()
});

global.XMLHttpRequest = require('xhr2');
global.dataLayer = [];
var test = require('blue-tape');
var GeordiClient = require('../index');

test('Instantiate a client with default settings', function(t) {
  var geordi = new GeordiClient();
  t.equal(geordi.env, 'staging');
  t.equal(geordi.projectToken, 'unspecified');
  t.end();
});
test('Instantiate a client with older settings', function(t) {
  var geordi = new GeordiClient({server: 'production'});
  t.equal(geordi.env, 'production');
  t.end();
});
test('Log without a valid project token', function(t) {
  var geordi = new GeordiClient({projectToken:''});
  geordi.logEvent('test event')
    .then(function(response){
      t.fail('invalid project token should not be logged');
      t.end();
    })
    .catch(function(error){
      t.pass(error);
      t.end();
    });
});
test('Log with valid project token', function(t) {
  var geordi = new GeordiClient({projectToken: 'test/token'});
  geordi.logEvent('test event')
    .then(function(response){
      t.pass('Valid project token will allow logging');
      t.end();
    })
});
test('Update data on Geordi', function(t) {
  var geordi = new GeordiClient({projectToken: 'test/token'});
  geordi.update({projectToken: 'new/token'})
  t.equal(geordi.projectToken, 'new/token');
  t.end();
});

Test that server config hasn't broken


var objectTypes = {
    "boolean": false,
    "function": true,
    "object": true,
    "number": false,
    "string": false,
    "undefined": false
};

/*eslint-disable */
var _root = (objectTypes[typeof self] && self) || (objectTypes[typeof window] && window);
var freeGlobal = objectTypes[typeof global] && global;

if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
    _root = freeGlobal;
}
/*eslint-enable */

var _id = 0;

function ensureSymbol(root) {
    if (!root.Symbol) {
        root.Symbol = function symbolFuncPolyfill(description) {
            return "@@Symbol(" + description + "):" + (_id++) + "}";
        };
    }
    return root.Symbol;
}

function ensureObservable(Symbol) {
    if (!Symbol.observable) {
        if (typeof Symbol.for === "function") {
            Symbol.observable = Symbol.for("observable");
        } else {
            Symbol.observable = "@@observable";
        }
    }
}

function symbolForPolyfill(key) {
    return "@@" + key;
}

function ensureFor(Symbol) {
    if (!Symbol.for) {
        Symbol.for = symbolForPolyfill;
    }
}

function polyfillSymbol(root) {
    var Symbol = ensureSymbol(root);
    ensureObservable(Symbol);
    ensureFor(Symbol);
    return Symbol;
}

module.exports = polyfillSymbol(_root);

var objectTypes = {
    "boolean": false,
    "function": true,
    "object": true,
    "number": false,
    "string": false,
    "undefined": false
};

/*eslint-disable */
var _root = (objectTypes[typeof self] && self) || (objectTypes[typeof window] && window);
var freeGlobal = objectTypes[typeof global] && global;

if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
    _root = freeGlobal;
}
/*eslint-enable */

var _id = 0;

function ensureSymbol(root) {
    if (!root.Symbol) {
        root.Symbol = function symbolFuncPolyfill(description) {
            return "@@Symbol(" + description + "):" + (_id++) + "}";
        };
    }
    return root.Symbol;
}

function ensureObservable(Symbol) {
    /* eslint-disable dot-notation */
    if (!Symbol.observable) {
        if (typeof Symbol.for === "function") {
            Symbol["observable"] = Symbol.for("observable");
        } else {
            Symbol["observable"] = "@@observable";
        }
    }
    /* eslint-disable dot-notation */
}

function symbolForPolyfill(key) {
    return "@@" + key;
}

function ensureFor(Symbol) {
    /* eslint-disable dot-notation */
    if (!Symbol.for) {
        Symbol["for"] = symbolForPolyfill;
    }
    /* eslint-enable dot-notation */
}

function polyfillSymbol(root) {
    var Symbol = ensureSymbol(root);
    ensureObservable(Symbol);
    ensureFor(Symbol);
    return Symbol;
}

module.exports = polyfillSymbol(_root);

Fix transpilation error to support React Native


var should = require('should'),
    stylus = require('stylus'),
    fs = require('fs');

var stylusMatchTest = function() {
  var files = fs.readdirSync(__dirname + '/fixtures/stylus/styl/');

  files.forEach(function(file) {
    var fileName = file.replace(/.{5}$/, '');

    describe(fileName + ' method', function() {
      it('should match', function(done) {
        var str = fs.readFileSync(__dirname + '/fixtures/stylus/styl/' + fileName + '.styl', { encoding: 'utf8' });
        stylus(str)
          .import('stylus/jeet')
          .render(function(err, result) {
            var expected = fs.readFileSync(__dirname + '/fixtures/stylus/css/' + fileName + '.css', { encoding: 'utf8' });

            done(err, expected.should.be.exactly(result));
          });
      });
    });

  });

}

stylusMatchTest();

var stylus  = require('stylus'),
    fs      = require('fs'),
    should  = require('should');

function compare(name, done) {
  var str = fs.readFileSync(__dirname + '/fixtures/stylus/styl/' + name + '.styl', { encoding: 'utf8' });
  stylus(str)
    .import('stylus/jeet')
    .render(function(err, result) {
      fs.readFile(__dirname + '/fixtures/stylus/css/' + name + '.css', { encoding: 'utf8' }, function(e, expected) {
        done(err, expected.should.be.exactly(result));
      });
    });
}

// Stylus Comparison Tests
describe('compiling method', function() {
  it('should apply a translucent, light-gray background color to all elements', function(done) {
    compare('edit', done);
  });
  it('should center an element horizontally', function(done) {
    compare('center', done);
  });
});

Make testing function more solid


module.exports = LessError;
function LessError(parser, e, env) {
    var input = parser.getInput(e, env),
        loc = parser.getLocation(e.index, input),
        line = loc.line,
        col  = loc.column,
        callLine = e.call && parser.getLocation(e.call, input).line,
        lines = input.split('\n');

    this.type = e.type || 'Syntax';
    this.message = e.message;
    this.filename = e.filename || env.currentFileInfo.filename;
    this.index = e.index;
    this.line = typeof(line) === 'number' ? line + 1 : null;
    this.callLine = callLine + 1;
    this.callExtract = lines[callLine];
    this.stack = e.stack;
    this.column = col;
    this.extract = [
        lines[line - 1],
        lines[line],
        lines[line + 1]
    ];
}

LessError.prototype = new Error();
LessError.prototype.constructor = LessError;

var LessError = module.exports = function LessError(parser, e, env) {
    var input = parser.getInput(e, env),
        loc = parser.getLocation(e.index, input),
        line = loc.line,
        col  = loc.column,
        callLine = e.call && parser.getLocation(e.call, input).line,
        lines = input.split('\n');

    this.type = e.type || 'Syntax';
    this.message = e.message;
    this.filename = e.filename || env.currentFileInfo.filename;
    this.index = e.index;
    this.line = typeof(line) === 'number' ? line + 1 : null;
    this.callLine = callLine + 1;
    this.callExtract = lines[callLine];
    this.stack = e.stack;
    this.column = col;
    this.extract = [
        lines[line - 1],
        lines[line],
        lines[line + 1]
    ];
}

LessError.prototype = new Error();
LessError.prototype.constructor = LessError;

Fix LessError being used before being defined


var app = require('../load'),
    useCases = app.useCases,
    h = require('../configHelpers');

exports.index = function(req, res){
  res.json(app.useCases);
};

exports.create = function(req, res){
  h.overwriteConfigWithPath(req.body, app.config().configPath, req.body.name + '.json');
  app.useCases.push(req.body);
  res.json(app.useCases);
};

var app = require('../load'),
    useCases = app.useCases,
    h = require('../configHelpers');

exports.index = function(req, res){
  res.json(app.useCases);
};

exports.create = function(req, res){
  // TODO: do this check in ember, before hitting the route
  if (h.loadConfigWithPathConverted(app.config().configPath, req.body.name + '.json')) {
      res.send(409, 'Conflict: Use Case Already Exists');
  } else {
    h.overwriteConfigWithPath(req.body, app.config().configPath, req.body.name + '.json');
    app.useCases.push(req.body);
    res.json(app.useCases);
  }
};

Return 409 if creating a use case that already exists


/**
 *	Chat Component
 *  $("#chat").chat({
 *      ruleGroupName: "",
 *      style: ["block"],
 *      template: [1],
 *      environment: "1"|"2"|"3"
 *  });
 */

ui.chat = function(conf) {

   	var that = ui.object(); // Inheritance

    var getDomain = function(n) {
        switch (n) {
            case "1": return "mercadolidesa.com.ar"; break;
            case "2": return "mercadolistage.com.ar"; break;
            case "3": return "mercadolibre.com.ar"; break;
        }
    }

    if (conf.msg) {
        conf.ruleGroupName = conf.msg;
    }

    that.load = function() {
        loadChatGZ(conf.ruleGroupName, conf.element.id, conf.style||"block", conf.template||"1",conf.environment||"3");
    }

   	ui.get({
   	    method: "component",
   	    name: "chat",
   	    script: "http://www."+getDomain(conf.environment)+"/org-img/jsapi/chat/chatRBIScript.js",
   	    callback: function() {
       	    that.load();
        }
   	});

    that.publish = {
    	uid: conf.uid,
		element: conf.element,
        type: conf.type
    }

    return that.publish;

}

/**
 *	Chat Component
 *  $("#chat").chat({
 *      ruleGroupName: "",
 *      style: ["block"],
 *      template: [1],
 *      environment: "1"|"2"|"3"
 *  });
 */

ui.chat = function(conf) {

   	var that = ui.object(); // Inheritance

    var getDomain = function(n) {
        switch (n) {
            case "1": return "mercadolidesa.com.ar"; break;
            case "2": return "mercadolistage.com.ar"; break;
            case "3": return "mercadolibre.com.ar"; break;
        }
    }

    if (conf.msg) {
        conf.ruleGroupName = conf.msg;
    }

    that.load = function() {
        loadChatGZ(conf.ruleGroupName, conf.element.id, conf.style||"block", conf.template||"1",conf.environment||"3");
    }

   	ui.get({
   	    method: "component",
   	    name: "chat",
   	    script: "https://www."+getDomain(conf.environment)+"/org-img/jsapi/chat/chatRBIScript.js",
   	    callback: function() {
       	    that.load();
        }
   	});

    that.publish = {
    	uid: conf.uid,
		element: conf.element,
        type: conf.type
    }

    return that.publish;

}

Change https protocol for Chat component


var Handlebars = require("handlebars/base");
module.exports = Handlebars;

require("handlebars/utils");

require("handlebars/ast");
require("handlebars/printer");
require("handlebars/visitor");

require("handlebars/compiler");

// BEGIN(BROWSER)

// END(BROWSER)

var Handlebars = require("handlebars/base");
module.exports = Handlebars;

require("handlebars/utils");

require("handlebars/ast");
require("handlebars/printer");
require("handlebars/visitor");

require("handlebars/compiler/compiler");
require("handlebars/vm");

// BEGIN(BROWSER)

// END(BROWSER)

Update node loader for compiler/vm split


import React, { Component } from 'react';
import "./css/App.css";
import logo from "../public/logo.svg";
import Markdown from "./Markdown";
import TocHeader from "./TocHeader";

class App extends Component {
    render() {
        return (

FredBoat

                            Contents

                        <TocHeader activePage={this.props.page} page="index" name="Quickstart"/>
                        <TocHeader activePage={this.props.page} page="faq" name="FAQ"/>
                        <TocHeader activePage={this.props.page} page="terms" name="Terms of Service"/>
                        <TocHeader activePage={this.props.page} page="selfhosting" name="Selfhosting"/>
                        <TocHeader activePage={this.props.page} page="systemdservice" name="Selfhosting (systemd)"/>

                    <Markdown name={this.props.page}/>

        )
    }
}

export default App;

import React, { Component } from 'react';
import "./css/App.css";
import logo from "../public/logo.svg";
import Markdown from "./Markdown";
import TocHeader from "./TocHeader";

class App extends Component {
    render() {
        return (

FredBoat

                            Contents

                        <TocHeader activePage={this.props.page} page="index" name="Quickstart"/>
                        <TocHeader activePage={this.props.page} page="faq" name="FAQ"/>
                        <TocHeader activePage={this.props.page} page="selfhosting" name="Selfhosting"/>
                        <TocHeader activePage={this.props.page} page="systemdservice" name="Selfhosting (systemd)"/>
                        <TocHeader activePage={this.props.page} page="terms" name="Terms of Service"/>

                    <Markdown name={this.props.page}/>

        )
    }
}

export default App;

Move ToS to the bottom


'use strict';

var Heroku      = require('heroku-client');
var co          = require('co');
var heroku;

module.exports = {
  topic: 'access',
  needsAuth: true,
  needsApp: true,
  command: 'remove',
  description: 'Remove users from your app',
  help: 'heroku access:remove user@email.com --app APP',
  args: [{name: 'user', optional: false}],

  run: function (context) {
    let appName;

    appName = context.app;

    co(function* () {
      heroku = new Heroku({token: context.auth.password});
      yield heroku.apps(appName).collaborators(context.args.user).delete(function (err) {
        if (err) { throw err; }
        console.log(`Removing ${context.args.user} from application ${cli.color.cyan(appName)}...done`);
      });
    }).catch(function (err) {
      console.error(err);
    });
  }
};

'use strict';

var Heroku      = require('heroku-client');
var co          = require('co');
var heroku;

module.exports = {
  topic: 'access',
  needsAuth: true,
  needsApp: true,
  command: 'remove',
  description: 'Remove users from your app',
  help: 'heroku access:remove user@email.com --app APP',
  args: [{name: 'user', optional: false}],

  run: function (context) {
    let appName;

    appName = context.app;

    co(function* () {
      heroku = new Heroku({token: context.auth.password});
      yield heroku.apps(appName).collaborators(context.args.user).delete(function (err) {
        if (err) { throw err; }
        console.log(`Removing ${context.args.user} from application appName...done`);
      });
    }).catch(function (err) {
      console.error(err);
    });
  }
};

Remove is not ready yet


module.exports = function($http, $state, $location, $q, DocumentApiService,
                           DocumentRouteService, DocumentService, GlobalService, UserService, MathJaxService) {

    console.log('SEARCH SERVICE')

    var deferred = $q.defer();
    var apiServer = GlobalService.apiServer()

    this.query = function(searchText, scope, destination='documents') {

        if (UserService.accessTokenValid() == false) {

                searchText += '&public'

            }

         return $http.get('http://' + apiServer + '/v1/documents' + '?' + searchText  )
        .then(function(response){

          var jsonData = response.data
          var documents = jsonData['documents']

          if (documents.length == 0) { documents = [GlobalService.defaultDocumentID()] }

          DocumentService.setDocumentList(documents)

          var id = documents[0]['id']
          DocumentApiService.getDocument(id)
          DocumentApiService.getDocument(id).then(function(response) {

                $state.go('documents', {}, {reload: true})

              })
         })
    }
}

module.exports = function($http, $state, $location, $q, DocumentApiService,
                           DocumentRouteService, DocumentService, GlobalService, UserService, MathJaxService) {

    console.log('SEARCH SERVICE')

    var deferred = $q.defer();
    var apiServer = GlobalService.apiServer()

    this.query = function(searchText, scope, destination='documents') {

        if (UserService.accessTokenValid() == false) {

                searchText += '&public'

            }

         return $http.get('http://' + apiServer + '/v1/documents' + '?' + searchText  )
        .then(function(response){

          var jsonData = response.data
          var documents = jsonData['documents']

          if ((documents == undefined) || (documents.length == 0)) { documents = [GlobalService.defaultDocumentID()] }

          DocumentService.setDocumentList(documents)

          var id = documents[0]['id']
          DocumentApiService.getDocument(id)
          DocumentApiService.getDocument(id).then(function(response) {

                $state.go('documents', {}, {reload: true})

              })
         })
    }
}

Handle case of undefined document list as result of search


// This initializer exists only to make sure that the following
// imports happen before the app boots.
import { registerKeywords } from 'ember-a11y/ember-internals';
registerKeywords();

import Ember from 'ember';

export function initialize(application) {
  let startRouting = application.startRouting;
  application.startRouting = function() {
    console.log('here');
    startRouting.call(application);
  }
}

export default {
  name: 'ember-a11y',
  initialize
};

// This initializer exists only to make sure that the following
// imports happen before the app boots.
import Ember from 'ember';
import { registerKeywords } from 'ember-a11y/ember-internals';
registerKeywords();

let handlerInfos;
Ember.Router.reopen({
  didTransition(handlerInfos) {
    this._super(...arguments);
  }
});

export function initialize(application) {}

export default {
  name: 'ember-a11y',
  initialize
};

Stop monkeypatching all the things. Monkeypatch the right things.


var p;
var drawings = [];

var DrawingManager = function (p5Sketch) {
  p = p5Sketch;
};

DrawingManager.prototype.add = function (drawing) {
  console.log('Added ' + drawing);
  drawings.unshift(drawing);
}

DrawingManager.prototype.drawAll = function () {
  for (var i = drawings.length - 1; i >= 0; i--) {
    drawings[i].draw(p);

    if (drawings[i].done()) {
      drawings.splice(i, 1);
    }
  };
}

DrawingManager.prototype.update = function (pulse, config) {
  for (var i = drawings.length - 1; i >= 0; i--) {
    if (drawings[i].pulse.name === pulse.name) {
      drawings[i].update(p, pulse, config);
      console.log("UPDATED pulse", drawings[i].pulse.name);
    }
  }
}

DrawingManager.prototype.clear = function () {
  drawings = [];
}

module.exports = DrawingManager;

var p;
var drawings = [];
var lowerLayer = [];

var DrawingManager = function (p5Sketch) {
  p = p5Sketch;
};

DrawingManager.prototype.add = function (drawing) {
  if (drawing.pulse.layer) {
    lowerLayer.unshift(drawing);
  } else {
    console.log('Added ' + drawing);
    drawings.unshift(drawing);
  }
}

DrawingManager.prototype.drawAll = function () {
  for (var i = lowerLayer.length - 1; i >= 0; i--) {
    lowerLayer[i].draw(p);

    if (lowerLayer[i].done()) {
      lowerLayer.splice(i, 1);
    }
  };

  for (var i = drawings.length - 1; i >= 0; i--) {
    drawings[i].draw(p);

    if (drawings[i].done()) {
      drawings.splice(i, 1);
    }
  };
}

DrawingManager.prototype.update = function (pulse, config) {
  for (var i = drawings.length - 1; i >= 0; i--) {
    if (drawings[i].pulse.name === pulse.name) {
      drawings[i].update(p, pulse, config);
      console.log("UPDATED pulse", drawings[i].pulse.name);
    }
  }
}

DrawingManager.prototype.clear = function () {
  drawings = [];
}

module.exports = DrawingManager;

Add a lower layer to the drawing manager


"use strict";

const Registry = require('../util/registry');

/**
 * TODO: Could this be replaced with an InitRegistry?
 * @class
 * @memberOf Defiant.Plugin
 * @extends Defiant.util.Registry
 */
class PluginRegistry extends Registry {
  /**
   * @function
   * @param {Defiant.Plugin} obj The plugin to add to the registry.
   * @param {Defiant.Engine} engine The app engine.
   * @returns {Defiant.Plugin.PluginRegistry} The plugin registry.
   */
  set(obj, engine) {
    // Initialize the plugin.
    return super.set(new obj(engine));
  }
}

module.exports = PluginRegistry;

"use strict";

const Registry = require('../util/registry');

/**
 * TODO: Could this be replaced with an InitRegistry?
 * @class
 * @memberOf Defiant.Plugin
 * @extends Defiant.util.Registry
 */
class PluginRegistry extends Registry {
  /**
   * @function
   * @param {Defiant.Plugin} obj
   *   The plugin to add to the registry.
   * @param {Defiant.Engine} engine
   *   The app engine.
   * @returns {Defiant.Plugin.PluginRegistry}
   *   The plugin registry.
   */
  set(obj, engine) {
    // Initialize the plugin.
    return super.set(new obj(engine));
  }
}

module.exports = PluginRegistry;

Standardize Jsdoc style for Defiant.Plugin.PluginRegistry


var Graphite = require('graphite');
var Measured = require('measured');

var reportInterval = 5000;
var graphiteHost = process.env.GRAPHITE_HOST || null;
var graphitePort = process.env.GRAPHITE_PORT || 2003;
var envName = process.env.NODE_ENV || "unknown";
var processIdentifier = 'pid-' + process.pid;

var timer = null;
var graphite = null;
var data = Measured.createCollection('origami.polyfill.' + envName + '.' + processIdentifier);

if (graphiteHost) {
	graphite = Graphite.createClient('plaintext://'+graphiteHost+':'+graphitePort);
	timer = setInterval(function() {
		graphite.write(data.toJSON(), function(err) {
			if (err) {

				// Ignore timeouts
				if (err.code === 'ETIMEDOUT') return;

				console.error(err, err.stack);
				console.warn('Disabling graphite reporting due to error');
				clearTimeout(timer);
			}
		});
	}, reportInterval);
	timer.unref();
}

module.exports = data;

var Graphite = require('graphite');
var Measured = require('measured');

var reportInterval = 5000;
var graphiteHost = process.env.GRAPHITE_HOST || null;
var graphitePort = process.env.GRAPHITE_PORT || 2003;
var envName = process.env.NODE_ENV || "unknown";
var processIdentifier = 'pid-' + process.pid;

var timer = null;
var graphite = null;
var data = Measured.createCollection('origami.polyfill.' + envName + '.' + processIdentifier);

if (graphiteHost) {
	graphite = Graphite.createClient('plaintext://'+graphiteHost+':'+graphitePort);
	timer = setInterval(function() {
		graphite.write(data.toJSON(), function(err) {
			if (err) {

				// Ignore timeouts
				if (err.code === 'ETIMEDOUT') return;

				console.error(err, err.stack);
				console.warn('Disabling graphite reporting due to error');
				clearInterval(timer);
			}
		});
	}, reportInterval);
	timer.unref();
}

module.exports = data;

Fix segfault caused by using incorrect clear method


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

/**
 * Returns a random integer between min and max
 */
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * Build a digits code
 */
function digitsCode(size) {
  var s = size;
  var code = "";
  while (s > 0) {
    s--;
    code += getRandomInt(0, 9);
  }
  return code;
}

module.exports = {
  digitsCode: digitsCode
};

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

var crypto = require("crypto");

/**
 * Build a digits code
 */
function digitsCode(size) {
  var nbBytes = Math.ceil(size/2);
  return parseInt(crypto.randomBytes(nbBytes).toString("hex"), 16)
    .toString().substr(0, size);
}

module.exports = {
  digitsCode: digitsCode
};

Refactor digitCode to use /dev/urandom instead of Math.random. r=Tarek


const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');

function copyTemplate(appDir, templatePath) {
  fs.copySync(templatePath, appDir);
  fs.moveSync(
    path.join(appDir, 'gitignore'),
    path.join(appDir, '.gitignore'),
  );
}

function addPackageScripts(appDir) {
  const scripts = {
    start: 'landing-scripts start',
    build: 'landing-scripts build',
  };

  const packageJson = require(`${appDir}/package.json`);
  packageJson.scripts = scripts;
  fs.writeFileSync(
    path.join(appDir, 'package.json'),
    JSON.stringify(packageJson, null, 2),
  );
}

function init(appDir, appName, templatePath) {
  const isUsingYarn = fs.existsSync(path.join(appDir, 'yarn.lock'));
  const command = isUsingYarn ? 'yarn' : 'npm';

  copyTemplate(appDir, templatePath);
  addPackageScripts(appDir);
  console.log(chalk.green('Project ready!'));
  console.log();
  console.log('To start the project typing:');
  console.log();
  console.log(chalk.cyan('cd'), appName);
  console.log(chalk.cyan(command), 'start');
}

module.exports = init;

const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');

function copyTemplate(appDir, templatePath) {
  fs.copySync(templatePath, appDir);
  fs.removeSync('.gitignore');
  fs.moveSync(
    path.join(appDir, 'gitignore'),
    path.join(appDir, '.gitignore'),
  );
}

function addPackageScripts(appDir) {
  const scripts = {
    start: 'landing-scripts start',
    build: 'landing-scripts build',
  };

  const packageJson = require(`${appDir}/package.json`);
  packageJson.scripts = scripts;
  fs.writeFileSync(
    path.join(appDir, 'package.json'),
    JSON.stringify(packageJson, null, 2),
  );
}

function init(appDir, appName, templatePath) {
  const isUsingYarn = fs.existsSync(path.join(appDir, 'yarn.lock'));
  const command = isUsingYarn ? 'yarn' : 'npm';

  copyTemplate(appDir, templatePath);
  addPackageScripts(appDir);
  console.log(chalk.green('Project ready!'));
  console.log();
  console.log('To start the project typing:');
  console.log();
  console.log(chalk.cyan('cd'), appName);
  console.log(chalk.cyan(command), 'start');
}

module.exports = init;

Remove .gitignore on bootstrap the project


'use strict';

module.exports = function (mongoose) {
  var recallSchema = mongoose.Schema({
    Year: Number,
    Make: String,
    Model: String,
    Manufacturer: String,
    Component: String,
    Summary: String,
    Consequence: String,
    Remedy: String,
    Notes: String,
    NHTSACampaignNumber: String,
    ReportReceivedDate: String
  });
  mongoose.model('Recall', recallSchema);
};

'use strict';

module.exports = function (mongoose) {
  var recallSchema = mongoose.Schema({
    Year: { type: Number, index: true },
    Make: { type: String, index: true },
    Model: { type: String, index: true },
    Manufacturer: String,
    Component: String,
    Summary: String,
    Consequence: String,
    Remedy: String,
    Notes: String,
    NHTSACampaignNumber: String,
    ReportReceivedDate: String
  });
  recallSchema.set('autoIndex', false);
  recallSchema.index({ Year: 1, Make: 1, Model: 1 });
  mongoose.model('Recall', recallSchema);
};

Add indexes to Recall schema


/**
 * @class CM_FormField_Text
 * @extends CM_FormField_Abstract
 */
var CM_FormField_Text = CM_FormField_Abstract.extend({
  _class: 'CM_FormField_Text',

  /** @type Boolean */
  _skipTriggerChange: false,

  events: {
    'blur input, textarea': function() {
      this.trigger('blur');
    },
    'focus input, textarea': function() {
      this.trigger('focus');
    }
  },

  /**
   * @param {String} value
   */
  setValue: function(value) {
    this._skipTriggerChange = true;
    this.$('input, textarea').val(value);
    this._skipTriggerChange = false;
  },

  /**
   * @return {Boolean}
   */
  hasFocus: function() {
    return this.getInput().is(':focus');
  },

  enableTriggerChange: function() {
    var self = this;
    var $input = this.getInput();
    var valueLast = $input.val();
    var callback = function() {
      var value = this.value;
      if (value != valueLast) {
        valueLast = value;
        if (!self._skipTriggerChange) {
          self.trigger('change');
        }
      }
    };
    // `propertychange` and `keyup` needed for IE9
    $input.on('input propertychange keyup', callback);
  }
});

/**
 * @class CM_FormField_Text
 * @extends CM_FormField_Abstract
 */
var CM_FormField_Text = CM_FormField_Abstract.extend({
  _class: 'CM_FormField_Text',

  /** @type Boolean */
  _skipTriggerChange: false,

  events: {
    'blur input, textarea': function() {
      this.trigger('blur');
    },
    'focus input, textarea': function() {
      this.trigger('focus');
    },
    'change input, textarea': function() {
      this.triggerChange();
    }
  },

  /**
   * @param {String} value
   */
  setValue: function(value) {
    this._skipTriggerChange = true;
    this.$('input, textarea').val(value);
    this._skipTriggerChange = false;
  },

  /**
   * @return {Boolean}
   */
  hasFocus: function() {
    return this.getInput().is(':focus');
  },

  triggerChange: function() {
    if (this._skipTriggerChange) {
      return;
    }
    this.trigger('change');
  },

  enableTriggerChangeOnInput: function() {
    var self = this;
    var $input = this.getInput();
    var valueLast = $input.val();
    var callback = function() {
      var value = this.value;
      if (value != valueLast) {
        valueLast = value;
        this.triggerChange();
      }
    };
    // `propertychange` and `keyup` needed for IE9
    $input.on('input propertychange keyup', callback);
  }
});

Introduce triggerChange, use it on input/textarea change


import template from './builder.js';
import kms from './kms.js';
import cw from './post.js';
import auth from './auth.js';

exports.handler = (event, context, callback) => {
  console.log('Received event:', JSON.stringify(event, null, 2));

  // Encrypted Chatwork token
  const encCwtoken = process.env.CHATWORK_API_TOKEN || '';

  // Chatwork Room ID from queryString
  const roomId = event.pathParameters.room_id || '';

  // Payload from GitHub
  const payload = event.requestParameters;

  // GitHub Event Name
  const eventName = event.headers['X-GitHub-Event'] || event.headers['x-github-event'] || '';

  // Original API token
  const token = event.queryParameters.token || '';

  // API token key
  const tokenKey = process.env.API_TOKEN || '';

  auth.verify(token, tokenKey).then(() => Promise.all([
    kms.decrypt(encCwtoken),
    new Promise((resolve, reject) => {
      if (roomId != '') {
        resolve(roomId);
      } else {
        reject('roomId is blank.');
      }
    }),
    template.build(eventName, payload),
  ]))
  .then(payload => cw.message(
      payload[0], // Raw Chatwork token
      payload[1], // Chatwork Room ID
      payload[2], // Chatwork message body
    ))
  .then((res) => {
    context.succeed(res);
  })
  .catch((reason) => {
    console.log(reason);
    console.log('Not post to chatwork.');
    context.fail(reason);
  });
};

import template from './builder';
import kms from './kms';
import cw from './post';
import auth from './auth';

exports.handler = (event, context, callback) => {
  console.log('Received event:', JSON.stringify(event, null, 2));

  // Encrypted Chatwork token
  const encCwtoken = process.env.CHATWORK_API_TOKEN || '';

  // Chatwork Room ID from queryString
  const roomId = event.pathParameters.room_id || '';

  // Payload from GitHub
  const payload = event.requestParameters;

  // GitHub Event Name
  const eventName = event.headers['X-GitHub-Event'] || event.headers['x-github-event'] || '';

  // Original API token
  const token = event.queryParameters.token || '';

  // API token key
  const tokenKey = process.env.API_TOKEN || '';

  auth.verify(token, tokenKey).then(() => Promise.all([
    kms.decrypt(encCwtoken),
    new Promise((resolve, reject) => {
      if (roomId != '') {
        resolve(roomId);
      } else {
        reject('roomId is blank.');
      }
    }),
    template.build(eventName, payload),
  ]))
  .then(payload => cw.message(
      payload[0], // Raw Chatwork token
      payload[1], // Chatwork Room ID
      payload[2], // Chatwork message body
    ))
  .then((res) => {
    context.succeed(res);
  })
  .catch((reason) => {
    console.log(reason);
    console.log('Not post to chatwork.');
    context.fail(reason);
  });
};

Remove file extension js from import


// An array with a max length.
//
// When max length is surpassed, items are removed from
// the front of the array.

// Using Classes to extend Array is unsupported in Babel so this less
// ideal approach is taken: https://babeljs.io/docs/en/caveats#classes
export default function RollingArray(maxLength, ...items) {
  const array = new Array(...items);
  array.maxLength = maxLength;

  // Capture the originals of each array method, but
  // associate them with the array to prevent closures.
  array._push = array.push;
  array._splice = array.splice;
  array._unshift = array.unshift;

  // All mutable array methods build on top of insertAt
  array._insertAt = array.insertAt;

  // Bring the length back down to maxLength by removing from the front
  array._limit = function() {
    const surplus = this.length - this.maxLength;
    if (surplus > 0) {
      this.splice(0, surplus);
    }
  };

  array.push = function(...items) {
    this._push(...items);
    this._limit();
    return this.length;
  };

  array.splice = function(...args) {
    const returnValue = this._splice(...args);
    this._limit();
    return returnValue;
  };

  array.insertAt = function(...args) {
    const returnValue = this._insertAt(...args);
    this._limit();
    this.arrayContentDidChange();
    return returnValue;
  };

  array.unshift = function() {
    throw new Error('Cannot unshift onto a RollingArray');
  };

  return array;
}

// An array with a max length.
//
// When max length is surpassed, items are removed from
// the front of the array.

// Native array methods
let { push, splice } = Array.prototype;

// Ember array prototype extension
let { insertAt } = Array.prototype;

// Using Classes to extend Array is unsupported in Babel so this less
// ideal approach is taken: https://babeljs.io/docs/en/caveats#classes
export default function RollingArray(maxLength, ...items) {
  const array = new Array(...items);
  array.maxLength = maxLength;

  // Bring the length back down to maxLength by removing from the front
  array._limit = function() {
    const surplus = this.length - this.maxLength;
    if (surplus > 0) {
      this.splice(0, surplus);
    }
  };

  array.push = function(...items) {
    push.apply(this, items);
    this._limit();
    return this.length;
  };

  array.splice = function(...args) {
    const returnValue = splice.apply(this, args);
    this._limit();
    return returnValue;
  };

  // All mutable array methods build on top of insertAt
  array.insertAt = function(...args) {
    const returnValue = insertAt.apply(this, args);
    this._limit();
    this.arrayContentDidChange();
    return returnValue;
  };

  array.unshift = function() {
    throw new Error('Cannot unshift onto a RollingArray');
  };

  return array;
}

Use the prototype instead of "private" property backups


import React, {PropTypes} from 'react'

const UsersTable = ({users}) => (

            User
            Roles
            Permissions

          {
            users.length ? users.map((user) => (

                {user.name}
                {user.roles.map((r) => r.name).join(', ')}
                {user.permissions.map((p) => p.scope).join(', ')}

            )) : (() => (

You don't have any Users,
why not create one?

            ))()
          }

)

const {
  arrayOf,
  shape,
  string,
} = PropTypes

UsersTable.propTypes = {
  users: arrayOf(shape({
    name: string.isRequired,
    roles: arrayOf(shape({
      name: string,
    })),
    permissions: arrayOf(shape({
      name: string,
      scope: string.isRequired,
    })),
  })),
}

export default UsersTable

import React, {PropTypes} from 'react'

const UsersTable = ({users}) => (

            User
            Roles
            Permissions

          {
            users.length ? users.map((user) => (

                {user.name}
                {users.roles && user.roles.map((r) => r.name).join(', ')}
                {user.permissions.map((p) => p.scope).join(', ')}

            )) : (() => (

You don't have any Users,
why not create one?

            ))()
          }

)

const {
  arrayOf,
  shape,
  string,
} = PropTypes

UsersTable.propTypes = {
  users: arrayOf(shape({
    name: string.isRequired,
    roles: arrayOf(shape({
      name: string,
    })),
    permissions: arrayOf(shape({
      name: string,
      scope: string.isRequired,
    })),
  })),
}

export default UsersTable

Handle no roles on users table


define([
    'underscore',
    'backgrid',
    'orodatagrid/js/datagrid/formatter/number-formatter'
], function(_, Backgrid, NumberFormatter) {
    'use strict';

    var NumberCell;

    /**
     * Number column cell.
     *
     * @export  oro/datagrid/cell/number-cell
     * @class   oro.datagrid.cell.NumberCell
     * @extends Backgrid.NumberCell
     */
    NumberCell = Backgrid.NumberCell.extend({
        /** @property {orodatagrid.datagrid.formatter.NumberFormatter} */
        formatterPrototype: NumberFormatter,

        /** @property {String} */
        style: 'decimal',

        /**
         * @inheritDoc
         */
        initialize: function(options) {
            _.extend(this, options);
            NumberCell.__super__.initialize.apply(this, arguments);
            this.formatter = this.createFormatter();
        },

        /**
         * Creates number cell formatter
         *
         * @return {orodatagrid.datagrid.formatter.NumberFormatter}
         */
        createFormatter: function() {
            return new this.formatterPrototype({style: this.style});
        }
    });

    return NumberCell;
});

define([
    'underscore',
    'backgrid',
    'orodatagrid/js/datagrid/formatter/number-formatter'
], function(_, Backgrid, NumberFormatter) {
    'use strict';

    var NumberCell;

    /**
     * Number column cell.
     *
     * @export  oro/datagrid/cell/number-cell
     * @class   oro.datagrid.cell.NumberCell
     * @extends Backgrid.NumberCell
     */
    NumberCell = Backgrid.NumberCell.extend({
        /** @property {orodatagrid.datagrid.formatter.NumberFormatter} */
        formatterPrototype: NumberFormatter,

        /** @property {String} */
        style: 'decimal',

        /**
         * @inheritDoc
         */
        initialize: function(options) {
            _.extend(this, options);
            NumberCell.__super__.initialize.apply(this, arguments);
            this.formatter = this.createFormatter();
        },

        /**
         * Creates number cell formatter
         *
         * @return {orodatagrid.datagrid.formatter.NumberFormatter}
         */
        createFormatter: function() {
            return new this.formatterPrototype({style: this.style});
        },

        /**
         * @inheritDoc
         */
        render: function() {
            var render = NumberCell.__super__.render.apply(this, arguments);

            this.enterEditMode();

            return render;
        },

        /**
         * @inheritDoc
         */
        enterEditMode: function() {
            if (this.column.get('editable')) {
                NumberCell.__super__.enterEditMode.apply(this, arguments);
            }
        },

        /**
         * @inheritDoc
         */
        exitEditMode: function() {
            if (!this.column.get('editable')) {
                NumberCell.__super__.exitEditMode.apply(this, arguments);
            }
        }
    });

    return NumberCell;
});

Add a grid to popup - added possibility to render number cell as an editable field


define(function (require) {
    'use strict';

    var store = require('store');

    var items = new Vue({
        el: 'body',

        data: {
            items: [],
            domains: store.fetch(),
            domain: ''
        },

        ready: function () {
            var timer,
                that = this;

            this.$watch('domains', function (domains) {
                store.save(domains);
            });

            this.$watch('domain', function (value) {
                that.items = [];
                for (var i = 0; i < that.domains.length && value; i++) {
                    if (that.domains[i].name.indexOf(value) === 0) {
                        that.items.push(that.domains[i]);
                    }
                }
            });
       },

        methods: {

            onRemove: function (item) {
                this.domains.$remove(item.$data);
                this.domain = '';
            },

            onHandle: function (e) {
                var data,
                    value = this.domain.trim();

                if (e.keyCode === 13) {
                    this.domains.push({
                        name: value,
                        active: true
                    });
                    this.domain = '';
                }

                if (e.keyCode === 27) {
                    this.domain = value = '';
                }
            },

            domainFilter: function (self) {
                return self.name.indexOf(this.domain) === 0;
            }

        }
    });

});

define(function (require) {
    'use strict';

    var store = require('store');

    var items = new Vue({
        el: 'body',

        data: {
            items: [],
            domains: store.fetch(),
            domain: ''
        },

        ready: function () {
            var timer,
                that = this;

            this.$watch('domains', function (domains) {
                store.save(domains);
            });

            this.$watch('domain', function (value) {
                that.items = [];
                for (var i = 0; i < that.domains.length && value; i++) {
                    if (that.domains[i].name.indexOf(value) === 0) {
                        that.items.push(that.domains[i]);
                    }
                }
            });
       },

        methods: {

            onRemove: function (item) {
                this.domains.$remove(item.$data);
                this.domain = '';
            },

            onHandle: function (e) {
                var data,
                    value = this.domain.trim();

                function parse(input) {
                    var regex = /((?:https?:\/\/)?(?:[^\.]*\.)*?)([^\.]*\.\w+)(\/.*)?$/;

                    return input.replace(regex, function (match, p1, p2, p3) {
                        p1 = p1 || '';
                        p2 = p2 || '';
                        p3 = p3 || '';
                        return p1 + p2.bold() + p3;
                    });
                }

                if (e.keyCode === 13) {
                    this.domains.push({
                        name: value,
                        active: true
                    });
                    this.domain = '';
                } else if (e.keyCode === 27) {
                    this.domain = value = '';
                } else {
                    //this.domain = parse(value);
                }
            },

            domainFilter: function (self) {
                return self.name.indexOf(this.domain) === 0;
            }

        }
    });

});

Add domain detect and show bold font of domain


var jadeStream = require('jade-stream')
var http = require('http')
var st = require('st')

var mount = st({
  path: 'app/assets',
  index: 'index.jade'
})

var app = http.createServer(function server(req, res) {
  if (req.url === '/')
    res.filter = jadeStream()

  mount(req, res)
})

app.listen(process.env.port, function listening() {
  var info = app.address()
  console.log('App running on http://%s:%s', info.address, info.port)
})

var jadeStream = require('jade-stream')
var config = require('rc')('bc-webplayer');
var http = require('http')
var st = require('st')

var mount = st({
  path: 'app/assets',
  index: 'index.jade',
  cache: config.cache
})

var app = http.createServer(function server(req, res) {
  if (req.url === '/')
    res.filter = jadeStream()

  mount(req, res)
})

app.listen(process.env.port, function listening() {
  var info = app.address()
  console.log('App running on http://%s:%s', info.address, info.port)
})

Add project settings via rc


const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const ZipPlugin = require("zip-webpack-plugin");
const path = require("path");

const package = require("./package");
const widgetName = package.name;
const widgetNameContext = widgetName + "Context";
const widgetVersion = package.version;

 module.exports = {
    entry: {
        [widgetName]: [ "core-js/es/promise", `./src/${widgetName}/widget/${widgetName}.js` ],
        [widgetNameContext]: [ "core-js/es/promise", `./src/${widgetName}/widget/${widgetNameContext}.js` ],
    },
    output: {
        path: path.resolve(__dirname, "dist/tmp/src"),
        filename: `${widgetName}/widget/[name].js`,
        chunkFilename: `${widgetName}/widget/${widgetName}[id].js`,
        libraryTarget: "amd",
        publicPath: "widgets/"
    },
    devtool: false,
    mode: "production",
    externals: [ /^mxui\/|^mendix\/|^dojo\/|^dijit\// ],
    plugins: [
        new webpack.LoaderOptionsPlugin({ debug: true }),
        new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: "dist/tmp" }),
        new CopyWebpackPlugin([ {context: "src", from: "**/*.xml", debug: true} ], { copyUnmodified: true }),
        new ZipPlugin({ path: `../../${widgetVersion}`, filename: widgetName, extension: "mpk" })
    ]
};

const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const ZipPlugin = require("zip-webpack-plugin");
const path = require("path");

const package = require("./package");
const widgetName = package.name;
const widgetNameContext = widgetName + "Context";
const widgetVersion = package.version;

 module.exports = {
    entry: {
        [widgetName]: [ "core-js/es/promise", `./src/${widgetName}/widget/${widgetName}.js` ],
        [widgetNameContext]: [ "core-js/es/promise", `./src/${widgetName}/widget/${widgetNameContext}.js` ],
    },
    output: {
        path: path.resolve(__dirname, "dist/tmp/src"),
        filename: `${widgetName}/widget/[name].js`,
        chunkFilename: `${widgetName}/widget/${widgetName}[id].js`,
        libraryTarget: "amd",
        publicPath: "/widgets/"
    },
    devtool: false,
    mode: "production",
    externals: [ /^mxui\/|^mendix\/|^dojo\/|^dijit\// ],
    plugins: [
        new webpack.LoaderOptionsPlugin({ debug: true }),
        new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: "dist/tmp" }),
        new CopyWebpackPlugin([ {context: "src", from: "**/*.xml", debug: true} ], { copyUnmodified: true }),
        new ZipPlugin({ path: `../../${widgetVersion}`, filename: widgetName, extension: "mpk" })
    ]
};

Fix widgets path when using pages that have an ID (e.g. //host/p/Page)


const webpack = require('webpack');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: './dist/html2canvas.js',
        library: 'html2canvas'
    },
    module: {
        loaders: [{
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        }]
    },
    plugins: [
        new webpack.DefinePlugin({
            '__DEV__': true
        })
    ]
};

const webpack = require('webpack');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: './dist/html2canvas.js',
        library: 'html2canvas',
        libraryTarget: 'umd'
    },
    module: {
        loaders: [{
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        }]
    },
    plugins: [
        new webpack.DefinePlugin({
            '__DEV__': true
        })
    ]
};

Define browser build target as umd


var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')

module.exports = {
  context: __dirname,

  entry: './webapp/assets/js/index', // entry point of our app. assets/js/index.js should require other js modules and dependencies it needs

  output: {
      path: path.resolve('./webapp/assets/bundles/'),
      filename: "[name]-[hash].js",
  },

  plugins: [
    new BundleTracker({filename: './webpack-stats.json'}),
  ],

  module: {
    loaders: [
      {
          test: /\.jsx?$/,
          exclude: /node_modules/,
          loader: 'babel',
          query:
            {
                presets:['react', 'es2015', 'stage-2']
            }
      }, // to transform JSX into JS
    ],
  },

  resolve: {
    modulesDirectories: ['node_modules', 'bower_components'],
    extensions: ['', '.js', '.jsx']
  },

  watchOptions: {
    poll: 1000,
    aggregateTimeout: 1000
  },
}

var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')

module.exports = {
  context: __dirname,

  entry: './webapp/assets/js/index', // entry point of our app. assets/js/index.js should require other js modules and dependencies it needs

  output: {
      path: path.resolve('./webapp/assets/bundles/'),
      filename: "[name]-[hash].js",
  },

  plugins: [
    new BundleTracker({filename: './webpack-stats.json'}),
  ],

  module: {
    loaders: [
      {
          test: /\.jsx?$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          query:
            {
                presets:['react', 'es2015', 'stage-2']
            }
      }, // to transform JSX into JS
    ],
  },

  resolve: {
    modulesDirectories: ['node_modules', 'bower_components'],
    extensions: ['', '.js', '.jsx']
  },

  watchOptions: {
    poll: 1000,
    aggregateTimeout: 1000
  },
}

Use babel loader instead of babel to production


const config = {
  entry: './src/index.js'
};

module.exports = config;

const path = require('path'); // We can use whatever nodejs package

const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'build'), //./build
    filename: 'bundle.js'
  }
};

module.exports = config;

Set name and path of the output file