/**
 * Background tasks
 */
class PathmarksBackground {

	static standardIcon() {
		chrome.browserAction.setIcon({path: '../images/icon38.png'});
	}

	static devBadge() {
		if (chrome.runtime.getManifest().short_name === 'PathDev') {
			chrome.browserAction.setBadgeText({text: "µ"});
			chrome.browserAction.setBadgeBackgroundColor({color: '#753015'});
		}
	}

}

/**
 * Upgrade tasks
 */
class PathmarksUpgrade {

	static upgradeToSyncStorage() {
		chrome.storage.local.get('pathmarks', (store) => {
			if (store['pathmarks']) {
				console.log("Local storage entries found. Convert to sync storage...");
				chrome.storage.sync.set(store, () => {
					console.log('Copy pathmarks to sync storage.');
					chrome.storage.local.clear(() => {
						console.log("Remove local storage entries");
						console.log('Conversion to sync storage completed.');
					});
				});
			}
		});
	}

}

chrome.runtime.onInstalled.addListener(() => PathmarksUpgrade.upgradeToSyncStorage());

chrome.runtime.onInstalled.addListener(() => PathmarksBackground.devBadge());

chrome.runtime.onConnect.addListener((port) => {
	port.onDisconnect.addListener(() => PathmarksBackground.standardIcon());
});

/**
 * Background tasks
 */
class PathmarksBackground {

	static standardIcon() {
		chrome.browserAction.setIcon({path: '../images/icon38.png'});
	}

	static devBadge() {
		if (chrome.runtime.getManifest().short_name === 'PathDev') {
			chrome.browserAction.setBadgeText({text: "µ"});
			chrome.browserAction.setBadgeBackgroundColor({color: 'rgb(80,80,80)'});
		}
	}

}

/**
 * Upgrade tasks
 */
class PathmarksUpgrade {

	static upgradeToSyncStorage() {
		chrome.storage.local.get('pathmarks', (store) => {
			if (store['pathmarks']) {
				console.log("Local storage entries found. Convert to sync storage...");
				chrome.storage.sync.set(store, () => {
					console.log('Copy pathmarks to sync storage.');
					chrome.storage.local.clear(() => {
						console.log("Remove local storage entries");
						console.log('Conversion to sync storage completed.');
					});
				});
			}
		});
	}

}

chrome.runtime.onInstalled.addListener(() => PathmarksUpgrade.upgradeToSyncStorage());

chrome.runtime.onInstalled.addListener(() => PathmarksBackground.devBadge());

chrome.runtime.onConnect.addListener((port) => {
	port.onDisconnect.addListener(() => PathmarksBackground.standardIcon());
});

Make development version badge less prominent


'use strict';

var Q = require('q');

module.exports = {
  findByName: function(name) {
    var deferred = Q.defer();

    if(name === null || name === undefined) {
      deferred.reject('What are we supposed to name you?');
      return deferred.promise;
    }

    User.findOne({ name: name }).exec(function(err, user) {
      if(user) {
        deferred.reject('You can\'t take a name already in use.');
        return;
      }
      if(err) {
        deferred.reject(err);
        return;
      }

      User.create({ name: name }).exec(function(err, user) {
        if(err) {
          deferred.reject(err);
        }
        deferred.resolve(user);
      });
    });

    return deferred.promise;
  },

  removeByUser: function(user) {
    var deferred = Q.defer();

    User.destroy({ id: user.id }).exec(function(err) {
      if(err) {
        deferred.reject(err);
      }
      else {
        deferred.resolve();
      }
    });

    return deferred.promise;
  }
};

'use strict';

var Q = require('q');

module.exports = {
  findByName: function(name) {
    var deferred = Q.defer();

    if(name === null || name === undefined) {
      deferred.reject('What are we supposed to name you?');
      return deferred.promise;
    }

    User.findOne({ name: name }).exec(function(err, user) {
      if(user) {
        deferred.reject('Sorry, someone already claimed that name!');
        return;
      }
      if(err) {
        deferred.reject(err);
        return;
      }

      User.create({ name: name }).exec(function(err, user) {
        if(err) {
          deferred.reject(err);
        }
        deferred.resolve(user);
      });
    });

    return deferred.promise;
  },

  removeByUser: function(user) {
    var deferred = Q.defer();

    User.destroy({ id: user.id }).exec(function(err) {
      if(err) {
        deferred.reject(err);
      }
      else {
        deferred.resolve();
      }
    });

    return deferred.promise;
  }
};

Replace the take name error with one that made more sense to display on the login view.


// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

window.onload = function() {
  chrome.management.getAll(function(items) {
    for (var i in items) {
      var item = items[i];
      if (item.name == "packaged_app") {
        chrome.management.launchApp(item.id);
        break;
      }
      if (item.name == "simple_extension") {
        // Try launching a non-app extension, which should fail.
        var expected_error = "Extension " + item.id + " is not an App";
        chrome.management.launchApp(item.id, function() {
          if (chrome.extension.lastError &&
              chrome.extension.lastError.message == expected_error) {
            chrome.test.sendMessage("got_expected_error");
          }
        });
      }
    }
  });
};

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

window.onload = function() {
  chrome.management.getAll(function(items) {
    for (var i in items) {
      var item = items[i];
      if (item.name == "packaged_app") {
        chrome.management.launchApp(item.id);
      }
      if (item.name == "simple_extension") {
        // Try launching a non-app extension, which should fail.
        var expected_error = "Extension " + item.id + " is not an App";
        chrome.management.launchApp(item.id, function() {
          if (chrome.extension.lastError &&
              chrome.extension.lastError.message == expected_error) {
            chrome.test.sendMessage("got_expected_error");
          }
        });
      }
    }
  });
};

Fix ExtensionManagementApiBrowserTest.LaunchApp to no longer be order-dependent.


// import dependencies
import {uniqueId} from '../../utils/helpers.js'
import template from './form-select.html'

// export component object
export default {
  template: template,
  replace: true,
  computed: {
    allOptions(){
        if (this.defaultOption.length) {
            return [this.defaultOption].concat(this.options)
        }
        return this.options
    },
  	inputState() {
      return !this.state || this.state === `default` ? `` : `has-${this.state}`
    },
    inputSize() {
      return !this.size || this.size === `default` ? `` : `form-control-${this.size}`
    },
  },
  props: {
    model: {
      twoWay: true,
      required: true
    },
    options: {
      type: Array,
      default: [],
      required: true,
    },
    id: {
      type: String,
      default: uniqueId
    },
    label: {
      type: String,
      default: false
    },
    defaultOption: {
      type: Object,
      default() {
        return {}
      }
    },
    description: {
      type: String,
      default: false
    },
    size: {
      type: String,
      default: ''
    },
    state: {
      type: String,
      default: ''
    },
  },
  watch: {
    model(val, oldVal) {
      if (val === oldVal) return
      // Dispatch an event from the current vm that propagates all the way up to it's $root
      this.$dispatch('selected::option', val)
    }
  }
}

// import dependencies
import {uniqueId} from '../../utils/helpers.js'
import template from './form-select.html'

// export component object
export default {
  template: template,
  replace: true,
  computed: {
    allOptions(){
        if (this.defaultOption.text && this.defaultOption.value) {
            return [this.defaultOption].concat(this.options)
        }
        return this.options
    },
  	inputState() {
      return !this.state || this.state === `default` ? `` : `has-${this.state}`
    },
    inputSize() {
      return !this.size || this.size === `default` ? `` : `form-control-${this.size}`
    },
  },
  props: {
    model: {
      twoWay: true,
      required: true
    },
    options: {
      type: Array,
      default: [],
      required: true,
    },
    id: {
      type: String,
      default: uniqueId
    },
    label: {
      type: String,
      default: false
    },
    defaultOption: {
      type: Object,
      default() {
        return {}
      }
    },
    description: {
      type: String,
      default: false
    },
    size: {
      type: String,
      default: ''
    },
    state: {
      type: String,
      default: ''
    },
  },
  watch: {
    model(val, oldVal) {
      if (val === oldVal) return
      // Dispatch an event from the current vm that propagates all the way up to it's $root
      this.$dispatch('selected::option', val)
    }
  }
}

Fix formSelect component's default option


var path = require('path');

module.exports = {
  name: 'Ember CLI Data Factory Guy',

  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints');
  },

  included: function(app) {
    this._super.included(app);

    if (app.tests) {
      // ember-data must be imported before ember-data-factory-guy.
      var options = {
        exports: {
          'ember-data': [
            'default'
          ]
        }
      };

      this.app.import({
        development: app.bowerDirectory + '/ember-data/ember-data.js',
        production: app.bowerDirectory + '/ember-data/ember-data.prod.js'
      }, options);

      app.import(app.bowerDirectory + '/ember-data-factory-guy/dist/ember-data-factory-guy.min.js');
    }
  }
};

var path = require('path');

module.exports = {
  name: 'Ember CLI Data Factory Guy',

  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints');
  },

  included: function(app) {
    this._super.included(app);

    if (app.tests) {
      // ember-data must be imported before ember-data-factory-guy.
      var options = {
        exports: {
          'ember-data': [
            'default'
          ]
        }
      };

      this.app.import({
        development: app.bowerDirectory + '/ember-data/ember-data.js',
        production: app.bowerDirectory + '/ember-data/ember-data.prod.js'
      }, options);

      app.import({
        development: app.bowerDirectory + '/ember-data-factory-guy/dist/ember-data-factory-guy.js',
        production: app.bowerDirectory + '/ember-data-factory-guy/dist/ember-data-factory-guy.min.js'
      });
    }
  }
};

Use unminified for development env


var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "../../../plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "../../../../plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

Fix no data error on cde dashboard


// nicknameblacklist.js
//
// list of banished nicknames
//
// Copyright 2017, Ryan Riddle
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

"use strict";

module.exports = ["api",
                  "oauth",
                  "public",
                  "robots.txt",
                  "humans.txt",
                  ".well-known",
                  "sitemap.xml",
                  "favicon.ico"];

// nicknameblacklist.js
//
// list of banished nicknames
//
// Copyright 2017, Ryan Riddle
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

"use strict";

module.exports = ["api",
                  "oauth",
                  "public",
                  "robots.txt",
                  "humans.txt",
                  ".well-known",
                  "sitemap.xml",
                  "favicon.ico",
                  "contribute.json"];

Add contribute.json to the nickname blacklist


var GNOVEL = GNOVEL || {};

(function() {
	"use strict";

	/**
	 * @class  MouseMovedCamera
	 * If created, will enable effect of mouse moved camera (small shift in the camera's direction vector according to mouse movement)
	 * @param {[GNOVEL.Gnovel]} gnovel
	 * @constructor
	 */
	var MouseMovedCamera = function(gnovel) {
		this._gnovel = gnovel;

		document.addEventListener('mousemove', function(event) {onDocumentMouseMove(event, gnovel);}, false);
	};

	function onDocumentMouseMove( event, gnovelObj ) {
		var mouseX = -( event.clientX - window.innerWidth / 2 ) / 4;
		var mouseY = ( event.clientY - window.innerHeight / 2 ) / 4;
		var camera = gnovelObj.getCamera();

		camera.position.x += ( mouseX - camera.position.x ) * .005;
		camera.position.y += ( mouseY - camera.position.y ) * .005;

		camera.position.x = THREE.Math.clamp(camera.position.x, -60, 60);
		camera.position.y = THREE.Math.clamp(camera.position.y, -40, 40);

		console.log(mouseY + " " + camera.position.y);
		camera.lookAt(new THREE.Vector3(0, 0, 400));
	};

	GNOVEL.MouseMovedCamera = MouseMovedCamera;
}());

var GNOVEL = GNOVEL || {};

(function() {
	"use strict";

	/**
	 * @class  MouseMovedCamera
	 * If created, will enable effect of mouse moved camera (small shift in the camera's direction vector according to mouse movement)
	 * @param {[GNOVEL.Gnovel]} gnovel
	 * @constructor
	 */
	var MouseMovedCamera = function(gnovel) {
		this._gnovel = gnovel;

		document.addEventListener('mousemove', function(event) {onDocumentMouseMove(event, gnovel);}, false);
	};

	function onDocumentMouseMove( event, gnovelObj ) {
		var mouseX = -( event.clientX - window.innerWidth / 2 ) / 4;
		var mouseY = ( event.clientY - window.innerHeight / 2 ) / 4;
		var camera = gnovelObj.getCamera();

		camera.position.x += ( mouseX - camera.position.x ) * .005;
		camera.position.y += ( mouseY - camera.position.y ) * .005;

		camera.position.x = THREE.Math.clamp(camera.position.x, -60, 60);
		camera.position.y = THREE.Math.clamp(camera.position.y, -18, 18);

		console.log(mouseY + " " + camera.position.y);
		camera.lookAt(new THREE.Vector3(0, 0, 400));
	};

	GNOVEL.MouseMovedCamera = MouseMovedCamera;
}());

Adjust limited mouse based camera movement


'use strict';

var w2v = require( './../lib' );

w2v.loadModel( __dirname + '/fixtures/vectors.txt', function( err, model ) {
	console.log( model );

	var wordVecs = model.getVectors( [ 'Hamlet', 'daughter' ] );
	console.log( wordVecs );
	console.log( model.getNearestWord( wordVecs[0].values, 1 ) );

	var similar = model.mostSimilar( 'dead', 20 );
	console.log( similar );

	var analogy = model.analogy( 'mother',[ 'Hamlet', 'father' ], 10 );
	console.log( analogy );

	var similarity = model.similarity( 'father', 'mother' );
	console.log( similarity );
});

'use strict';

var w2v = require( './../lib' );

w2v.loadModel( __dirname + '/fixtures/vectors.txt', function( err, model ) {
	console.log( model );

	var wordVecs = model.getVectors( [ 'Hamlet', 'daughter' ] );
	console.log( model.getNearestWord( wordVecs[0].values, 1 ) );

	var similar = model.mostSimilar( 'dead', 20 );
	console.log( similar );

	var analogy = model.analogy( 'mother',[ 'Hamlet', 'father' ], 10 );
	console.log( analogy );

	var similarity = model.similarity( 'father', 'mother' );
	console.log( similarity );
});

Remove unwanted console.log statement in example code


angular.module('OpiferEntityPicker', ['ui.bootstrap.typeahead'])

    .directive('entityPicker', function() {

        var tpl =
            '<input type="text" ng-model="search" typeahead="object.name for object in getObject($viewValue)" typeahead-on-select="onSelect($item, $model, $label)" typeahead-loading="loadingLocations" class="form-control">' +
            '<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>';

        return {
            restrict: 'E',
            transclude: true,
            scope: {
                url: '=',
                subject: '='
            },
            template: tpl,
            controller: function($scope, $http, $attrs) {

                // Get the object by search term
                $scope.getObject = function(term) {
                    return $http.get($scope.url, {
                        params: {
                            term: term
                        }
                    }).then(function(response){
                        return response.data.map(function(item){
                            return item;
                        });
                    });
                };

                // Select the object
                $scope.onSelect = function(item, model, label) {
                    if (angular.isUndefined($scope.subject.right.value)) {
                        $scope.subject.right.value = [];
                    }

                    if ($scope.subject.right.value.indexOf(item.id) == -1) {
                        $scope.subject.right.value.push(item.id);
                    }

                    $scope.search = null;
                };
            }
        };
    })
;

angular.module('OpiferEntityPicker', ['ui.bootstrap.typeahead'])

    .directive('entityPicker', function() {

        var tpl =
            '<input type="text" ng-model="search" typeahead="object.name for object in getObject($viewValue)" typeahead-on-select="onSelect($item, $model, $label)" typeahead-loading="loadingLocations" class="form-control">' +
            '<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>';

        return {
            restrict: 'E',
            transclude: true,
            scope: {
                url: '=',
                subject: '='
            },
            template: tpl,
            controller: function($scope, $http, $attrs) {

                // Get the object by search term
                $scope.getObject = function(term) {
                    return $http.get($scope.url, {
                        params: {
                            term: term
                        }
                    }).then(function(response){
                        return response.data.map(function(item){
                            return item;
                        });
                    });
                };

                // Select the object
                $scope.onSelect = function(item, model, label) {
                    if (angular.isUndefined($scope.subject.right.value)) {
                        $scope.subject.right.value = [];
                    }

                    var item = {id:item.id, name:item.name};

                    if ($scope.subject.right.value.indexOf(item) == -1) {
                        $scope.subject.right.value.push(item);
                    }

                    $scope.search = null;
                };
            }
        };
    })
;

Return a simple object when an entity is picked


// redis host
exports.queue= {};
exports.queue.redis_host = '10.95.8.182';

exports.dbrelayer = {};
exports.dbrelayer.key_prefix = 'wrH:';
exports.dbrelayer.redis_host = '10.95.8.182';
exports.dbrelayer.expire_time = 60;

// redis host
exports.queue= {};
exports.queue.redis_host = '10.95.8.182';

exports.dbrelayer = {}
exports.dbrelayer.key_prefix = 'wrH:';
exports.dbrelayer.redis_host = '10.95.8.182';
exports.expire_time = 60;

Revert "expire_time into dbrelayer section"


'use strict';

/**
 * Render the splash page of application
 */
exports.renderSplash = function (req,res) {
  res.render('modules/core/server/views/splash', {
    user: req.user || null
  });
};

/**
 * Render the main application page
 */
exports.renderIndex = function (req, res) {
  res.render('modules/core/server/views/index', {
    user: req.user || null
  });
};

/**
 * Render the server error page
 */
exports.renderServerError = function (req, res) {
  res.status(500).render('modules/core/server/views/500', {
    error: 'Oops! Something went wrong...'
  });
};

/**
 * Render the server not found responses
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderNotFound = function (req, res) {

  res.status(404).format({
    'text/html': function () {
      res.render('modules/core/server/views/404', {
        url: req.originalUrl
      });
    },
    'application/json': function () {
      res.json({
        error: 'Path not found'
      });
    },
    'default': function () {
      res.send('Path not found');
    }
  });
};

'use strict';

/**
 * Render the main application page
 */
exports.renderIndex = function (req, res) {
  res.render('modules/core/server/views/index', {
    user: req.user || null
  });
};

/**
 * Render the server error page
 */
exports.renderServerError = function (req, res) {
  res.status(500).render('modules/core/server/views/500', {
    error: 'Oops! Something went wrong...'
  });
};

/**
 * Render the server not found responses
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderNotFound = function (req, res) {

  res.status(404).format({
    'text/html': function () {
      res.render('modules/core/server/views/404', {
        url: req.originalUrl
      });
    },
    'application/json': function () {
      res.json({
        error: 'Path not found'
      });
    },
    'default': function () {
      res.send('Path not found');
    }
  });
};

Remove reference to old splplash.html


Change local storage key prefix back to "x-font-" for fontload.js.


var mode = 0; //primary

function calc_mode() {
	var modes = ["primary", "secondary", "tertiary"];
	return modes[mode];
}

function send_data() {
	$.ajax({
		url: "calculate/"+primary+"/"+secondary+"/"+tertiary,
		context: document.body,
		type: "post",
		beforeSend :function() {
			//loading
		}
	}).done(function(data) {

	});
}

$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
	$("#effects_table table").tablesorter();

	$("#calc_ingredients tbody").find('tr').each(function(){
		$(this).click(function(){
			$('#'+calc_mode()).html($(this).text());
			send_data();
		});
	});

	$("#primary").click(function(){
		$(this).text('--');
		mode = 0;
	});

	$("#secondary").click(function(){
		$(this).text('--');
		mode = 1;
	});

	$("#tertiary").click(function(){
		$(this).text('--');
		mode = 2;
	});
});

var mode = 0; //primary

function mode_text() {
	var modes = ["primary", "secondary", "tertiary"];
	return modes[mode];
}

function send_data() {
	$.ajax({
		url: "calculate/"+primary+"/"+secondary+"/"+tertiary,
		context: document.body,
		type: "post",
		beforeSend :function() {
			//loading
		}
	}).done(function(data) {

	});
}

$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
	$("#effects_table table").tablesorter();

	$("#calc_ingredients tbody").find('tr').each(function(){
		$(this).click(function(){
			$('#'+mode_text()).html($(this).text());
			send_data();
		});
	});

	$("#primary").click(function(){
		$(this).text('--');
		mode = 0;
	});

	$("#secondary").click(function(){
		$(this).text('--');
		mode = 1;
	});

	$("#tertiary").click(function(){
		$(this).text('--');
		mode = 2;
	});
});

Change calc mode to mode text function name


'use strict';

var fs = require('fs');

module.exports = function(app) {
	return function(req, res) {
		fs.readFile(app.get('appPath') + '/version.json', 'utf8', function(err, data) {
			if (err) {
				res.status(404).end('Not found');
			} else {
				res.type('json').send(data);
			}
		});
	};
};

'use strict';

var fs = require('fs');

module.exports = function(app) {
	return function(req, res) {
		res.sendfile(app.get('appPath') + '/version.json');
	};
};

Simplify the server version component


function Client() {

}

Client.prototype = {
  chain: [],

  events: { },

  register: function(action) {
    if(this.chain.length > 0) {
      this.chain.push(action);

      return;
    }

    action(callback);
  },

  on: function(eventType, action) {
    var event = this.events[eventType] = this.events[eventType] || [];
    event.push(action);
  },

  set: function(key, value, callback) {
    this.register(function() {
      openReadable(function(os) {
        // TODO do stuff with objectStore
        callback();
      });
    });

    return this;
  }
};

function Client() {

}

Client.prototype = {
  chain: [],

  events: { },

  register: function(action) {
    if(this.chain.length > 0) {
      this.chain.push(action);

      return;
    }

    action(callback);
  },

  on: function(eventType, action) {
    var event = this.events[eventType] = this.events[eventType] || [];
    event.push(action);
  },

  set: function(key, value, callback) {
    this.register(function() {
      openWritable(function(os) {
        // TODO do stuff with objectStore
        callback();
      });
    });

    return this;
  }
};

Set should use a writeable database.


function loadScript(url, callback){
  var script = document.createElement("script")
  script.type = "text/javascript";

  if (script.readyState){  //IE
    script.onreadystatechange = function(){
      if (script.readyState == "loaded" ||
          script.readyState == "complete"){
        script.onreadystatechange = null;
        callback();
      }
    };
  } else {  //Others
    script.onload = function(){callback();};
  }

  script.src = url;
  document.documentElement.insertBefore(script, document.documentElement.firstChild);
}

loadScript("build/compressed_all.js", function(){});

// http://drnicwilliams.com/2006/11/21/diy-widgets/
jsgvLoader = function() {
  var BASE_URL = 'http://localhost/jsgameviewer/';
  var STYLESHEET = BASE_URL + "build/compressed.css"
  var JAVASCRIPT = BASE_URL + "build/compressed_all.js"

  return {
    loadStylesheet: function(stylesheet_url) {
      stylesheet = document.createElement("link");
      stylesheet.rel = "stylesheet";
      stylesheet.type = "text/css";
      stylesheet.href = stylesheet_url;
      stylesheet.media = "all";
      document.lastChild.firstChild.appendChild(stylesheet);
    },

    loadJavascript: function(url, callback){
      var script = document.createElement("script")
      script.type = "text/javascript";

      if (script.readyState){  //IE
        script.onreadystatechange = function(){
          if (script.readyState == "loaded" || script.readyState == "complete"){
            script.onreadystatechange = null;
            callback();
          }
        };
      } else {  //Others
        script.onload = function(){callback();};
      }

      script.src = url;
      document.lastChild.firstChild.appendChild(script);
      // document.documentElement.insertBefore(script, document.documentElement.firstChild);
    },

    load: function(){
      this.loadStylesheet();
      this.loadJavascript();
    }
  };
}();

window.onload(function(){
  if (document.getElementByClass('jsgv')) {
    jsgvLoader.load();
  }
});

Load javascript and css across website


const Eris = require("eris");
const config = require("./cfg");

const intents = [
  // PRIVILEGED INTENTS
  "guildMembers", // For server greetings

  // REGULAR INTENTS
  "directMessages", // For core functionality
  "guildMessages", // For bot commands and mentions
  "guilds", // For core functionality
  "guildVoiceStates", // For member information in the thread header
  "guildMessageTyping", // For typing indicators
  "directMessageTyping", // For typing indicators

  // EXTRA INTENTS (from the config)
  ...config.extraIntents,
];

const bot = new Eris.Client(config.token, {
  restMode: true,
  intents: Array.from(new Set(intents)),
  allowedMentions: {
    everyone: false,
    roles: false,
    users: false,
  },
});

/**
 * @type {Eris.Client}
 */
module.exports = bot;

const Eris = require("eris");
const config = require("./cfg");

const intents = [
  // PRIVILEGED INTENTS
  "guildMembers", // For server greetings

  // REGULAR INTENTS
  "directMessages", // For core functionality
  "guildMessages", // For bot commands and mentions
  "guilds", // For core functionality
  "guildVoiceStates", // For member information in the thread header
  "guildMessageTyping", // For typing indicators
  "directMessageTyping", // For typing indicators

  // EXTRA INTENTS (from the config)
  ...config.extraIntents,
];

const bot = new Eris.Client(config.token, {
  restMode: true,
  intents: Array.from(new Set(intents)),
  allowedMentions: {
    everyone: false,
    roles: false,
    users: false,
  },
});

bot.on("error", err => {
  if (err.code === 1006) {
    // 1006 = "Connection reset by peer"
    // Eris allegedly handles this internally, so we can ignore it
    return;
  }

  throw err;
});

/**
 * @type {Eris.Client}
 */
module.exports = bot;

Handle error 1006 (Connection reset by peer) gracefully


'use strict';

import { API_LOGIN_SUCCESS, API_SIGNUP_SUCCESS } from 'app/actions/auth';
import {
  SET_PAGE_LOGIN_STATE,
  SET_PAGE_SIGNUP_STATE,
  SET_OVERRIDE_FRAME,
  CLEAR_OVERRIDE_FRAME
} from 'app/actions/landingPage';
import { initialLPState } from 'app/constants';

export default function landingPageState(state = initialLPState, action) {
  switch (action.type) {
    case SET_PAGE_LOGIN_STATE:
      return { ...state, frame: 'login' };
    case SET_PAGE_SIGNUP_STATE:
      return { ...state, frame: 'signup' };
    case SET_OVERRIDE_FRAME:
      return { ...state, overrideFrame: action.frame };
    case CLEAR_OVERRIDE_FRAME:
    case API_LOGIN_SUCCESS:
    case API_SIGNUP_SUCCESS:
      return initialLPState;
  }

  return state;
}

'use strict';

import { LOGOUT } from 'app/actions/auth';
import {
  SET_PAGE_LOGIN_STATE,
  SET_PAGE_SIGNUP_STATE,
  SET_OVERRIDE_FRAME,
  CLEAR_OVERRIDE_FRAME
} from 'app/actions/landingPage';
import { initialLPState } from 'app/constants';

export default function landingPageState(state = initialLPState, action) {
  switch (action.type) {
    case SET_PAGE_LOGIN_STATE:
      return { ...state, frame: 'login' };
    case SET_PAGE_SIGNUP_STATE:
      return { ...state, frame: 'signup' };
    case SET_OVERRIDE_FRAME:
      return { ...state, overrideFrame: action.frame };
    case CLEAR_OVERRIDE_FRAME:
    case LOGOUT:
      return initialLPState;
  }

  return state;
}

Reset landing page state only upon logout


'use strict';

const Utils = require("../../util/utils");

module.exports = class FeatureList {

    constructor() {
        this.features = []
    }

    add(properties, geometry) {
        let feature = {
            type: "Feature",
            geometry: Utils.sortObject(geometry),
            properties: Utils.sortObject(properties)
        };

        this.features.push(feature);
    }

    getFeatures() {
        return this.features;
    }

    getFeatureCollection() {
        return {
            type: "FeatureCollection",
            features: this.features,
        };
    }

    static createFromArray(array) {
        if (!array.hasOwnProperty("features")) {
            throw("Supplied JSON does not contain required property 'features'");
        }

        let instance = new FeatureList();
        let features = array.features;

        for (let i in features) {
            instance.add(features[i].properties, features[i].geometry)
        }

        return instance;
    }
};

'use strict';

const Utils = require("../../util/utils");

module.exports = class FeatureList {

    constructor() {
        this.features = []
    }

    add(properties, geometry) {
        let feature = {
            geometry: Utils.sortObject(geometry),
            properties: Utils.sortObject(properties),
            type: "Feature"
        };

        this.features.push(feature);
    }

    getFeatures() {
        return this.features;
    }

    getFeatureCollection() {
        return {
            type: "FeatureCollection",
            features: this.features,
        };
    }

    static createFromArray(array) {
        if (!array.hasOwnProperty("features")) {
            throw("Supplied JSON does not contain required property 'features'");
        }

        let instance = new FeatureList();
        let features = array.features;

        for (let i in features) {
            instance.add(features[i].properties, features[i].geometry)
        }

        return instance;
    }
};

Put data into alphabetical order


/**
 * Dispatches the "contentchange" events. The detail may be different,
 * but the eventType is always "contentchange"
 *
 * @param contentElement
 * @param detail
 */
function dispatchContentChangeEvent(contentElement, detail) {
	let event = new CustomEvent("contentchange", {
		detail: detail
	});
	contentElement.dispatchEvent(event);
}

/**
 * Acts as a pass-through for a MutationRecord
 *
 * @param contentElement
 * @param mutationRecord
 */
export function contentChangeEvent(contentElement, mutationRecord) {
	dispatchContentChangeEvent(contentElement, mutationRecord);
}

/**
 * Sets up a "contentchange" event that passes an array of added nodes
 *
 * @param contentElement
 * @param nodes
 */
export function nodesAddedToContentEvent(contentElement, nodes) {
	dispatchContentChangeEvent(contentElement, {
		type: 'nodesAdded',
		nodesAdded: nodes
	});
}

/**
 * Sets up a "contentchange" event that passes an array of removed nodes
 *
 * @param contentElement
 * @param nodes
 */
export function nodesRemovedFromContentEvent(contentElement, nodes) {
	dispatchContentChangeEvent(contentElement, {
		type: 'nodesRemoved',
		nodesRemoved: nodes
	});
}

export default {};

/**
 * Dispatches the "contentchange" events. The detail may be different,
 * but the eventType is always "contentchange"
 *
 * @param contentElement
 * @param detail
 */
function dispatchContentChangeEvent(contentElement, detail) {
	let event = new CustomEvent("contentchange", {
		detail: detail
	});
	contentElement.dispatchEvent(event);
}

/**
 * Acts as a pass-through for a MutationRecord
 *
 * @param contentElement
 * @param mutationRecord
 */
export function contentChangeEvent(contentElement, mutationRecord) {
	dispatchContentChangeEvent(contentElement, {
		type: 'mutation',
		mutation: mutationRecord
	});
}

/**
 * Sets up a "contentchange" event that passes an array of added nodes
 *
 * @param contentElement
 * @param nodes
 */
export function nodesAddedToContentEvent(contentElement, nodes) {
	dispatchContentChangeEvent(contentElement, {
		type: 'nodesAdded',
		nodesAdded: nodes
	});
}

/**
 * Sets up a "contentchange" event that passes an array of removed nodes
 *
 * @param contentElement
 * @param nodes
 */
export function nodesRemovedFromContentEvent(contentElement, nodes) {
	dispatchContentChangeEvent(contentElement, {
		type: 'nodesRemoved',
		nodesRemoved: nodes
	});
}

export default {};

Set the MutationRecord inside of the detail, not as the detail


import * as types from '../constants/actionTypes';

export function updateArchetype(value) {
  return {
    type: types.UPDATE_ARCHETYPE,
    payload: {
      archetype: value
    }
  };
}

export function updateClan(value) {
  return {
    type: types.UPDATE_CLAN,
    payload: {
      clan: value
    }
  };
}

import * as types from '../constants/actionTypes';

export const updateArchetype = value => ({
  type: types.UPDATE_ARCHETYPE,
  payload: {
    archetype: value
  }
});

export const updateClan = value => ({
  type: types.UPDATE_CLAN,
  payload: {
    clan: value
  }
});

Convert action creators to arrow functions


var Backbone = require('backbone');

module.exports = Backbone.Model.extend({
  defaults: {
    beenSet: true, //set this back to false when done testing
    guid: "8f9c3e25c0e196647f83fa704a59c6b76f15b686", //for testing with test server only
    name: "Your Name",
    handle: "Blockchain ID",
    avatar_hash: "",
    tempAvatar: "",
    bitcoinAddress: "",
    currency: "US Dollar",
    currencyCode: "USD",
    country: "UNITED_STATES", //set to blank when done testing //this is the country code, like UNITED_STATES
    language: "en",
    timeZome: "",
    notifications: true,
    shipToName: "",
    shipToStreet: "",
    shipToCity: "",
    shipToState: "",
    shipToPostalCode: "",
    shipToCountry: "",
    blocked: ["handle1", "handle2", "handle3"],
    libbitcoinServer: "",
    SSL: false,
    seedPhrase: "",
    //server: "http://localhost:18469/api/v1/"
    //values below for testing. Real value should be dynamically set
    server: "http://seed.openbazaar.org:18469/api/v1/"
    //server: "http://bitcoinauthenticator.org:18469/api/v1/"
  }
});

var Backbone = require('backbone');

module.exports = Backbone.Model.extend({
  defaults: {
    beenSet: true, //set this back to false when done testing
    guid: "8f9c3e25c0e196647f83fa704a59c6b76f15b686", //for testing with test server only
    name: "Your Name",
    handle: "Blockchain ID",
    avatar_hash: "",
    tempAvatar: "",
    bitcoinAddress: "",
    currency: "US Dollar",
    currencyCode: "USD",
    country: "UNITED_STATES", //set to blank when done testing //this is the country code, like UNITED_STATES
    language: "en",
    timeZome: "",
    notifications: true,
    shipToName: "",
    shipToStreet: "",
    shipToCity: "",
    shipToState: "",
    shipToPostalCode: "",
    shipToCountry: "",
    blocked: ["handle1", "handle2", "handle3"],
    libbitcoinServer: "",
    SSL: false,
    seedPhrase: "",
    server: "http://localhost:18469/api/v1/"
    //values below for testing. Real value should be dynamically set
    //server: "http://seed.openbazaar.org:18469/api/v1/"
    //server: "http://bitcoinauthenticator.org:18469/api/v1/"
  }
});

Update Server back to local


var postcss = require('postcss'),
    color = require('color');

module.exports = postcss.plugin('postcss-lowvision', function () {
    return function (css) {
        css.walkDecls('color', function (decl) {
            var val = decl.value;
            var rgb = color(val);
            rgb = rgb.rgbArray();
            decl.value = 'transparent';
            decl.cloneAfter({ prop: 'text-shadow',
                              value: '0 0 5px rgba(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ', ' + '1)' });
        });
        css.walkRules('img', function (decl) {
        // Find all filter declarations
        css.walkDecls('filter', function (decl) {
            // Add blur filter to existing filters
            decl.value = 'blur(5px) ' + decl.value;
         });
            decl.append({ prop: 'filter',  value: 'blur(5px)' });
        });
    };
});

var postcss = require('postcss'),
    color = require('color');

module.exports = postcss.plugin('postcss-lowvision', function () {
    return function (css) {
        css.walkDecls('color', function (decl) {
            var val = decl.value;
            var rgb = color(val);
            rgb = rgb.rgbArray();
            decl.value = 'transparent';
            decl.cloneAfter({ prop: 'text-shadow',
                              value: '0 0 5px rgba(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ', ' + '1)' });
        });
        css.walkRules('img', function (decl) {
        // Find all filter declarations
        css.walkDecls('filter', function (decl) {
            // Add blur filter to existing filters
            decl.value = 'blur(5px) ' + decl.value;
         });
        //find all images in css
      	css.walkRules('img', function (decl) {
            //Add blur filter to images
            decl.append({ prop: 'filter',  value: 'blur(5px)' });
        });
    };
});

Add blur filter to all images in css


'use strict';

angular.module('seblucas.slGridListToggle', [])
  .directive('slGridListToggle', function() {
    return {
      restrict: 'E',
      require: '^ngModel',
      scope: {
        templatePrefix: '='
      },
      template:
'
 \
  <button ng-repeat="item in toggles" type="button" class="btn btn-default" ng-class="{active: isTemplateActive(item)}" ng-click="toggleTemplate(item)"> \
     \
  </button> \

',
      link: function(scope, element, attrs, ngModel) {
        scope.toggles = ['th', 'list'];
        ngModel.$render = function() {
            scope.currentTemplate = ngModel.$modelValue;
        };

        scope.toggleTemplate = function(value) {
          scope.currentTemplate = scope.templatePrefix + value +'.html';
          ngModel.$setViewValue(scope.currentTemplate);
        };

        scope.isTemplateActive = function(value) {
          return scope.currentTemplate.indexOf ('.' + value + '.html') > 0;
        };
      }
    };
  });

'use strict';

/*!
 * angular-bootstrap-grid-list-toggle
 * https://github.com/seblucas/angular-bootstrap-grid-list-toggle
 * Copyright (c) 2015 ; Licensed MIT
 */
angular.module('seblucas.slGridListToggle', [])
  .directive('slGridListToggle', function() {
    return {
      restrict: 'E',
      require: '^ngModel',
      scope: {
        templatePrefix: '='
      },
      template:
'
 \
  <button ng-repeat="item in toggles" type="button" class="btn btn-default" ng-class="{active: isTemplateActive(item)}" ng-click="toggleTemplate(item)"> \
     \
  </button> \

',
      link: function(scope, element, attrs, ngModel) {
        scope.toggles = ['th', 'list'];
        ngModel.$render = function() {
            scope.currentTemplate = ngModel.$modelValue;
        };

        scope.toggleTemplate = function(value) {
          scope.currentTemplate = scope.templatePrefix + value +'.html';
          ngModel.$setViewValue(scope.currentTemplate);
        };

        scope.isTemplateActive = function(value) {
          return scope.currentTemplate.indexOf ('.' + value + '.html') > 0;
        };
      }
    };
  });

Add header to the source file


var mongoose = require('mongoose');

var periodSchema = new mongoose.Schema({
    day: Date,
    start_time: Date,
    end_time: Date,
    title: String,
    linked_day: Number
});

var daySchema = new mongoose.Schema({
    date: Date,
    period_list: Array,
    title: String,
    linked_day_type: Number
});

var dayTypeSchema = new mongoose.Schema({
    date: Date,
    type: String
});

var Period = mongoose.model('Period', periodSchema);
var Day = mongoose.model('Day', daySchema);
var DayType = mongoose.model('DayType', dayTypeSchema);

module.exports = {
        Period: Period,
        Day: Day,
        DayType: DayType
};

var mongoose = require('mongoose');

var periodSchema = new mongoose.Schema({
    day: Date,
    start_time: Date,
    end_time: Date,
    title: String,
    linked_day: String
});

var daySchema = new mongoose.Schema({
    date: Date,
    period_list: Array,
    title: String,
    linked_day_type: String
});

var dayTypeSchema = new mongoose.Schema({
    date: Date,
    type: String
});

var Period = mongoose.model('Period', periodSchema);
var Day = mongoose.model('Day', daySchema);
var DayType = mongoose.model('DayType', dayTypeSchema);

module.exports = {
        Period: Period,
        Day: Day,
        DayType: DayType
};

Update models to handle ids correctly


define([
	"dojo/_base/declare"
], function (declare) {
	return declare(null, {
		// summary:
		//		Adds functionality for creating relationships between destroyable or removable objects and this object
		//		where they should all be destroyed together.
		// _owned: Object[]
		//		Items that are owned by this object.
		_owned: [],
		own: function () {
			// summary:
			//		Creates a relationship where this object is the owner of provided items.
			//		Items should have either destroyRecursive, destroy, or remove method.
			this._owned = this._owned.concat(Array.prototype.slice.call(arguments, 0));
		},
		destroy: function () {
			// summary:
			//		Removes all owned items before this object is destroyed.
			var owned = this._owned,
				i = 0,
				peon;

			while (peon = owned[i++]) {
				if (peon.destroyRecursive) {
					peon.destroyRecursive();
				} else if (peon.destroy) {
					peon.destroy();
				} else if (peon.remove) {
					peon.remove();
				}
			}

			this.inherited(arguments);
		}
	});
});

define([
	"dojo/_base/declare"
], function (declare) {
	return declare(null, {
		// summary:
		//		Adds functionality for creating relationships between destroyable or removable objects and this object
		//		where they should all be destroyed together.
		// _owned: Object[]
		//		Items that are owned by this object.
		_owned: null,
		buildRendering: function () {
			this._owned = [];
		},
		own: function () {
			// summary:
			//		Creates a relationship where this object is the owner of provided items.
			//		Items should have either destroyRecursive, destroy, or remove method.
			this._owned = this._owned.concat(Array.prototype.slice.call(arguments, 0));
		},
		destroy: function () {
			// summary:
			//		Removes all owned items before this object is destroyed.
			var owned = this._owned,
				i = 0,
				peon;

			while (peon = owned[i++]) {
				if (peon.destroyRecursive) {
					peon.destroyRecursive();
				} else if (peon.destroy) {
					peon.destroy();
				} else if (peon.remove) {
					peon.remove();
				}
			}

			this.inherited(arguments);
		}
	});
});

Initialize _owned during buildRendering to prevent shared _owned


'use strict';

var reqRegEx = /\s*(?:\{(.*)\})?\s*(?:(\$?[^\s]+))?\s*(?:\(([^\)]*)\))?\s*(?:-?\s*(.*?))\s*$/;

module.exports = {

  parse: function (text) {
    var match = reqRegEx.exec(text.trim());

    var obj = {
      type: match[1] || 'Map'
    };

    if (match[2]){
      obj.path = match[2];
    }

    if (match[3]){
      obj.default = match[3];
    }

    if (match[4]){
      obj.description = match[4];
    }

    return obj;
  }

};

'use strict';

var reqRegEx = /\s*(?:\{(.*)\})?\s*(?:(\$?[^\s]+))?\s*(?:\(([^\)]*)\))?\s*(?:-?\s*(.*?))\s*$/;

module.exports = {

  parse: function (text) {
    var match = reqRegEx.exec(text.trim());

    var obj = {
      type: match[1] || 'Map'
    };

    if (match[2]){
      obj.name = match[2];
    }

    if (match[3]){
      obj.default = match[3];
    }

    if (match[4]){
      obj.description = match[4];
    }

    return obj;
  }

};

Rename `path` in `name` to be consistent


/**
 * Use this to make an object that rests on the couch.

var couch = CouchDB.rest("http://localhost:5984/example/");

 * Then, just read and write.

// writes to database using HTTP PUT behind the scenes.
couch.someDocument = { foo : "bar" }

// reads from database using HTTP GET behind the scenes
print(couch.someDocument.foo)

// you can write just part of a record, but it'll still PUT
// the whole thing back on the couch.
couch.someDocument.foo = "baz";

// remove from the database
delete couch.someDocument

// clear the caches, retrieve loose change.
CouchDB.vaccuum(couch)

 * This can be pretty slow.  Reads are cached, which mitigates it somewhat.
 * Writes are optimistic, and may need to update if the cache is out of date.
 **/

var {HTTPClient} = require("http-client"),
    JSON = require("json");

function jsonCleaner (obj) {
    if (typeof obj === "function") return obj.toString();
    return obj;
};

Add some spec for how this thing ought to work.


// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require_tree .

Remove remaining parts of turbo_links


'use strict'

/*!
 * multer
 * Copyright(c) 2014 Hage Yaapa
 * Copyright(c) 2015 Fangdun Cai
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

const originalMulter = require('multer')

function multer(options) {
  const m = originalMulter(options)

  const _makeMiddleware = m._makeMiddleware.bind(m)
  m._makeMiddleware = makePromise(_makeMiddleware)

  const any = m.any.bind(m)
  m.any = makePromise(any)

  return m
}

function makePromise(fn) {
  return (fields, fileStrategy) => {
    return (ctx, next) => {
      return new Promise((resolve, reject) => {
        fn(fields, fileStrategy)(ctx.req, ctx.res, (err) => {
          err ? reject(err) : resolve(ctx)
        })
      }).then(next)
    }
  }
}

multer.diskStorage = originalMulter.diskStorage
multer.memoryStorage = originalMulter.memoryStorage

module.exports = multer

'use strict'

/*!
 * multer
 * Copyright(c) 2014 Hage Yaapa
 * Copyright(c) 2015 Fangdun Cai
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

const originalMulter = require('multer')

function multer(options) {
  const m = originalMulter(options)

  makePromise(m, 'any')
  makePromise(m, 'array')
  makePromise(m, 'fields')
  makePromise(m, 'none')
  makePromise(m, 'single')

  return m
}

function makePromise(multer, name) {
  if (!multer[name]) return

  const fn = multer[name].bind(multer)

  multer[name] = (...args) => {
    return (ctx, next) => {
      return new Promise((resolve, reject) => {
        fn(...args)(ctx.req, ctx.res, (err) => {
          err ? reject(err) : resolve(ctx)
        })
      }).then(next)
    }
  }
}

multer.diskStorage = originalMulter.diskStorage
multer.memoryStorage = originalMulter.memoryStorage

module.exports = multer

Stop relying on internal functions


import Browser from './browser'
import Print from './print'

export default {
  print: (params, printFrame) => {
    // If showing feedback to user, pre load pdf files (hacky)
    if (params.showModal || Browser.isIE()) {
      let req = new window.XMLHttpRequest()
      req.addEventListener('load', send(params, printFrame))
      req.open('GET', window.location.href + params.printable, true)
      req.send()
    } else {
      send(params, printFrame)
    }
  }
}

function send (params, printFrame) {
  // Set iframe src with pdf document url
  printFrame.setAttribute('src', params.printable)

  Print.send(params, printFrame)
}

import Browser from './browser'
import Print from './print'

export default {
  print: (params, printFrame) => {
    // If showing feedback to user, pre load pdf files (hacky)
    if (params.showModal || Browser.isIE()) {
      let req = new window.XMLHttpRequest()
      req.addEventListener('load', send(params, printFrame))
      req.open('GET', window.location.origin + params.printable, true)
      req.send()
    } else {
      send(params, printFrame)
    }
  }
}

function send (params, printFrame) {
  // Set iframe src with pdf document url
  printFrame.setAttribute('src', params.printable)

  Print.send(params, printFrame)
}

Use window.origin instead of window.href


import React from "react";
import ReactDOM from "react-dom";
import $ from "jquery";
import Backbone from "backbone";

export default React.createClass({
    displayName: "Tag",

    propTypes: {
        tag: React.PropTypes.instanceOf(Backbone.Model).isRequired,
        renderLinks: React.PropTypes.bool
    },

    getDefaultProps: function() {
        return {
            renderLinks: true
        }
    },

    onClick(e) {
        let { onTagClick } = this.props;
        e.stopPropagation();
        e.preventDefault();
        // Still causing a warning
        // "Failed Context Types: Required context `router`"
        if (onTagClick) {
            onTagClick(this.props.tag);
        }
    },

    componentDidMount: function() {
        // FIXME:
        // https://github.com/yannickcr/eslint-plugin-react/issues/678#issue-165177220
        var el = ReactDOM.findDOMNode(this),
            $el = $(el),
            tag = this.props.tag;

        $el.tooltip({
            title: tag.get("description"),
            placement: "left"
        });
    },

    render: function() {
        var tag = this.props.tag,
            tagName = tag.get("name"),
            link;

        if (this.props.renderLinks) {
            link = (

                    {tagName}

            );
        } else {
            link = (

                    {tagName}

            )
        }

        return (

                {link}

        );
    }
});

import React from "react";
import ReactDOM from "react-dom";
import $ from "jquery";
import Backbone from "backbone";

export default React.createClass({
    displayName: "Tag",

    propTypes: {
        tag: React.PropTypes.instanceOf(Backbone.Model).isRequired,
        renderLinks: React.PropTypes.bool
    },

    getDefaultProps: function() {
        return {
            renderLinks: true
        }
    },

    onClick(e) {
        let { onTagClick } = this.props;
        e.stopPropagation();
        e.preventDefault();
        if (onTagClick) {
            onTagClick(this.props.tag);
        }
    },

    componentDidMount: function() {
        // FIXME:
        // https://github.com/yannickcr/eslint-plugin-react/issues/678#issue-165177220
        var el = ReactDOM.findDOMNode(this),
            $el = $(el),
            tag = this.props.tag;

        $el.tooltip({
            title: tag.get("description"),
            placement: "left"
        });
    },

    render: function() {
        var tag = this.props.tag,
            tagName = tag.get("name"),
            link;

        return (

                    {tagName}

        );
    }
});

Remove old comment, and unessary if logic


import ExpandablePanelModule from "./expandablePanel";

const { module } = angular.mock;

describe("ExpandablePanel", () => {
  beforeEach(module(ExpandablePanelModule));

  let $log;
  beforeEach(inject(($injector) => {
    $log = $injector.get("$log");
    $log.reset();
  }));
  afterEach(() => {
    $log.assertEmpty();
  });

  describe("Module", () => {
    it("is named expandablePanel", () => {
      expect(ExpandablePanelModule).to.equal("expandablePanel");
    });
  });

  describe("Controller", () => {
    let $componentController;
    beforeEach(inject(($injector) => {
      $componentController = $injector.get("$componentController");
    }));

    it("renders markdown", () => {
      let $ctrl = $componentController("expandablePanel", { }, { markdown: true });
      $ctrl.$onChanges({
        content: {
          currentValue: "sometext"
        }
      });
      expect($ctrl.parsed).to.equal("
sometext
\n");
    });
  });
});

import ExpandablePanelModule from "./expandablePanel";

const { module } = angular.mock;

describe("ExpandablePanel", () => {
  beforeEach(module(ExpandablePanelModule));

  let $log;
  beforeEach(inject(($injector) => {
    $log = $injector.get("$log");
    $log.reset();
  }));
  afterEach(() => {
    $log.assertEmpty();
  });

  describe("Module", () => {
    it("is named expandablePanel", () => {
      expect(ExpandablePanelModule).to.equal("expandablePanel");
    });
  });

  describe("Controller", () => {
    let $componentController;
    beforeEach(inject(($injector) => {
      $componentController = $injector.get("$componentController");
    }));

    it("renders markdown", () => {
      let $ctrl = $componentController("expandablePanel", { }, { markdown: true });
      $ctrl.$onChanges({
        content: {
          currentValue: "sometext"
        }
      });
      expect($ctrl.parsed).to.equal("
sometext
\n");
    });

    it("collapses long text", () => {
      let $ctrl = $componentController("expandablePanel", { });
      $ctrl.$onChanges({
        content: {
          currentValue: new Array(20).join("text\n")
        }
      });
      expect($ctrl.collapsed).to.be.true;
    });
  });
});

Add test for collapsed text


var HtmlScreenshotReporter = require("protractor-jasmine2-screenshot-reporter");
var JasmineReporters = require('jasmine-reporters');

exports.config = {
    seleniumServerJar: '../../../node_modules/protractor/selenium/selenium-server-standalone-2.47.1.jar',
    chromeDriver: '../../../node_modules/protractor/selenium/chromedriver',
    allScriptsTimeout: 20000,

    specs: [
        'e2e/*.js'
    ],

    capabilities: {
        'browserName': 'firefox',
        'phantomjs.binary.path': require('phantomjs').path,
        'phantomjs.ghostdriver.cli.args': ['--loglevel=DEBUG']
    },

    baseUrl: 'http://localhost:8080/',

    framework: 'jasmine2',

    jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 30000
    },

    onPrepare: function() {
        browser.driver.manage().window().setSize(1280, 1024);
        jasmine.getEnv().addReporter(new JasmineReporters.JUnitXmlReporter({
            savePath: '<% if (buildTool == 'maven') { %>target<% } else { %>build<% } %>/reports/e2e',
            consolidateAll: false
        }));
        jasmine.getEnv().addReporter(new HtmlScreenshotReporter({
            dest: "<% if (buildTool == 'maven') { %>target<% } else { %>build<% } %>/reports/e2e/screenshots"
        }));
    }
};

var HtmlScreenshotReporter = require("protractor-jasmine2-screenshot-reporter");
var JasmineReporters = require('jasmine-reporters');

exports.config = {
    seleniumServerJar: '../../../node_modules/protractor/selenium/selenium-server-standalone-2.47.1.jar',
    chromeDriver: '../../../node_modules/protractor/selenium/chromedriver',
    allScriptsTimeout: 20000,

    specs: [
        'e2e/*.js'
    ],

    capabilities: {
        'browserName': 'firefox',
        'phantomjs.binary.path': require('phantomjs').path,
        'phantomjs.ghostdriver.cli.args': ['--loglevel=DEBUG']
    },

    directConnect: true,

    baseUrl: 'http://localhost:8080/',

    framework: 'jasmine2',

    jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 30000
    },

    onPrepare: function() {
        browser.driver.manage().window().setSize(1280, 1024);
        jasmine.getEnv().addReporter(new JasmineReporters.JUnitXmlReporter({
            savePath: '<% if (buildTool == 'maven') { %>target<% } else { %>build<% } %>/reports/e2e',
            consolidateAll: false
        }));
        jasmine.getEnv().addReporter(new HtmlScreenshotReporter({
            dest: "<% if (buildTool == 'maven') { %>target<% } else { %>build<% } %>/reports/e2e/screenshots"
        }));
    }
};

Add directConnect to true in protractor tests - it's to avoid the Error: Timed out waiting for the WebDriver server


import { NodeComponent } from 'substance'
import katex from 'katex'

export default class InlineFormulaComponent extends NodeComponent {

  render($$) {
    const node = this.props.node
    // TODO: Find out why node.find('tex-math') returns null here
    const texMath = node.findChild('tex-math')
    const el = $$('span').addClass('sc-inline-formula')
    el.append(
      $$(TexMathComponent, {
        node: texMath
      }).ref('math')
    )
    if (this.props.isolatedNodeState) {
      el.addClass('sm-'+this.props.isolatedNodeState)
    }
    return el
  }
}

class TexMathComponent extends NodeComponent {
  render($$) {
    const node = this.props.node
    const texMath = node.textContent
    const el = $$('span').addClass('sc-math')
    if (!texMath) {
      el.append('???')
    } else {
      try {
        el.append(
          $$('span').html(katex.renderToString(texMath))
        )
        let blockerEl = $$('div').addClass('se-blocker')
        el.append(blockerEl)
      } catch (error) {
        el.addClass('sm-error')
          .text(error.message)
      }
    }
    return el
  }
}

import { NodeComponent } from 'substance'
import katex from 'katex'

export default class InlineFormulaComponent extends NodeComponent {

  render($$) {
    const node = this.props.node
    const texMath = node.find('tex-math')
    const el = $$('span').addClass('sc-inline-formula')
    el.append(
      $$(TexMathComponent, {
        node: texMath
      }).ref('math')
    )
    if (this.props.isolatedNodeState) {
      el.addClass('sm-'+this.props.isolatedNodeState)
    }
    return el
  }
}

class TexMathComponent extends NodeComponent {
  render($$) {
    const node = this.props.node
    const texMath = node.textContent
    const el = $$('span').addClass('sc-math')
    if (!texMath) {
      el.append('???')
    } else {
      try {
        el.append(
          $$('span').html(katex.renderToString(texMath))
        )
        let blockerEl = $$('div').addClass('se-blocker')
        el.append(blockerEl)
      } catch (error) {
        el.addClass('sm-error')
          .text(error.message)
      }
    }
    return el
  }
}

Remove workaround for broken el.find()


import React from 'react';
import {Link} from 'react-router';

export default class Header extends React.Component {
  render() {
    var offline = false;
    if (!navigator.onLine) offline = (offline);

    return (

          <Link to="builds" className="brand">
            Frigg CI
            {offline}
          </Link>

            <Link to="builds" className="button">Builds</Link>
            <StaffButton href="/stats/" text="Stats" {...this.props.user} />
            <StaffButton href="/admin/" text="Admin" {...this.props.user} />
            <LogInOutButton {...this.props.user} />

    );
  }
}

export class LogInOutButton extends React.Component {
  render() {
    if (this.props.is_anonymous === false) {
      return (
        Logout
      );
    } else {
      return (
        Login
      );
    }
  }
}

export class StaffButton extends React.Component {
  render() {
    if (this.props.is_staff === false) return false;
    return (
      {this.props.text}
    );
  }
}

import React from 'react';
import {Link} from 'react-router';

export default class Header extends React.Component {

  constructor() {
    super();
    this.state = {online: navigator.onLine};
  }

  componentDidMoun() {
    window.addEventListener('online', this.updateOnlineState.bind(this));
    window.addEventListener('offline', this.updateOnlineState.bind(this));
  }

  updateOnlineState() {
    this.setState({online: navigator.onLine});
  }

  render() {
    var offline = false;
    if (!this.state.online) offline = (offline);

    return (

          <Link to="builds" className="brand">
            Frigg CI
            {offline}
          </Link>

            <Link to="builds" className="button">Builds</Link>
            <StaffButton href="/stats/" text="Stats" {...this.props.user} />
            <StaffButton href="/admin/" text="Admin" {...this.props.user} />
            <LogInOutButton {...this.props.user} />

    );
  }
}

export class LogInOutButton extends React.Component {
  render() {
    if (this.props.is_anonymous === false) {
      return (
        Logout
      );
    } else {
      return (
        Login
      );
    }
  }
}

export class StaffButton extends React.Component {
  render() {
    if (this.props.is_staff === false) return false;
    return (
      {this.props.text}
    );
  }
}

Add handling of online/offline event


'use strict'

var fs = require('fs')
var miss = require('mississippi')
var config = require('../config')

function filterJobsList (jobs) {
  var list = []

  jobs.forEach(function (job) {
    if (job.indexOf('.json') > -1) {
      list.push(job)
    }
  })

  return list
}

var getNextJob = miss.through(function (chunck, encoding, callback) {
  var jobs = filterJobsList(fs.readdirSync(config.JOB_DIRECTORY_PATH))
  var item

  console.log('get-next-job')

  if (jobs.length > 0) {
    item = fs.readFileSync(config.JOB_DIRECTORY_PATH + '/' + jobs[0])
    return callback(null, item.toString())
  } else {
    return callback(new Error('No jobs in queue'), null)
  }
})

module.exports = getNextJob

'use strict'

var fs = require('fs')
var miss = require('mississippi')
var config = require('../config')

function filterJobsList (jobs) {
  var list = []

  jobs.forEach(function (job) {
    if (job.indexOf('.json') > -1) {
      list.push(job)
    }
  })

  return list
}

var getNextJob = miss.through(function (chunck, encoding, callback) {
  var jobs = filterJobsList(fs.readdirSync(config.JOB_DIRECTORY_PATH))
  var item

  console.log('get-next-job')

  if (jobs.length > 0) {
    item = fs.readFileSync(config.JOB_DIRECTORY_PATH + '/' + jobs[0])
    return callback(null, item.toString())
  } else {
    console.log('No jobs in queue')
    process.exit(0)
  }
})

module.exports = getNextJob

Use process.exit(0) if none found


(function() {
    var HashArg = {};
    HashArg.get = function(argdefs, argv) {
        var args = {};
        if(!argv) {
            argv = [];
            for(var i = 2; i < process.argv.length; i++) {
                argv.push(process.argv[i]);
            }
        }
        if(typeof(argdefs) === 'string') {
            argdefs = argdefs.split(/\s+/);
        }
        for(var i = 0; i < argdefs.length; i++) {
            var argdef = argdefs[i];
            var name = "#" + i;
            var value = null;
            if(typeof(argdef) === 'string') {
                name = argdef;
                if(i < argv.length) {
                    value = argv[i];
                }
            } else if("name" in argdef) {
                name = argdef.name;
                if(i < argv.length) {
                    value = argv[i];
                } else if("default" in argdef) {
                    value = argdef["default"];
                }
            }
            args[name] = value;
        }
        return args;
    };
    module.exports = HashArg;
}());

(function() {
    var HashArg = {};
    HashArg.get = function(argdefs, argv) {
        var args = {};
        if(!argv || argv === process.argv) {
            argv = [];
            for(var i = 2; i < process.argv.length; i++) {
                argv.push(process.argv[i]);
            }
        }
        if(typeof(argdefs) === 'string') {
            argdefs = argdefs.split(/\s+/);
        }
        for(var i = 0; i < argdefs.length; i++) {
            var argdef = argdefs[i];
            var name = "#" + i;
            var value = null;
            if(typeof(argdef) === 'string') {
                name = argdef;
                if(i < argv.length) {
                    value = argv[i];
                }
            } else if("name" in argdef) {
                name = argdef.name;
                if(i < argv.length) {
                    value = argv[i];
                } else if("default" in argdef) {
                    value = argdef["default"];
                }
            }
            args[name] = value;
        }
        return args;
    };
    module.exports = HashArg;
}());

Check if the 2nd param is process.argv and work well


'use strict';

var winston = require('winston');

var ScriptRunner = function(service,options){
	this.service = service;
	this.options = options || {};
};

ScriptRunner.prototype.run = function(method,script,options,cb){

	// If there is no incoming authentication, use ours
	if(!options.auth){
		options.auth = this.options.auth;
	}

	if(!options.logger){
		options.logger = new (winston.Logger)();
	}

	return this.service.runMethod(method,script,options,cb);
};

module.exports = ScriptRunner;

'use strict';

var winston = require('winston');

var ScriptRunner = function(service,options){
	this.service = service;
	this.options = options || {};
};

var MockScriptStore = function(){
	this.data = {};
};

MockScriptStore.prototype.get = function(key,cb){
	cb(null,(this.data && this.data[key] || null));
};

MockScriptStore.prototype.set = function(key,value,cb){
	this.data[key] = value;
	cb();
};

MockScriptStore.prototype.del = function(key,cb){
	delete this.data[key];
	cb();
};

ScriptRunner.prototype.run = function(method,script,options,cb){

	// If there is no incoming authentication, use ours
	if(!options.auth){
		options.auth = this.options.auth;
	}

	if(!options.logger){
		options.logger = new (winston.Logger)();
	}

	if(!options.scriptStore){
		options.scriptStore = new MockScriptStore;
	}

	return this.service.runMethod(method,script,options,cb);
};

module.exports = ScriptRunner;

Add basic mock of scriptrunner


var _ = require('underscore')._;

function SearchResult(options) {
	_.extend(this, _.pick(options,
		'url', 'permalink', 'siteMediaID',
		'siteCode', 'icon', 'author',
		'mediaName', 'duration', 'type'));
	var stats = {querySimilarity: 1, playRelevance: 1, favoriteRelevance: 1, relevance: 0.5};
	stats = _.extend(stats, _.pick(options, 'plays', 'favorites'));
	stats.plays = parseInt(stats.plays) || undefined;
	stats.favorites = parseInt(stats.favorites) || undefined;
	stats.querySimilarity = 1;
	stats.playRelevance = 1;
	stats.favoriteRelevance = 1;
	this.stats = stats;
}

SearchResult.prototype = {
	calculateRelevance: function() {
    	var lambdaPlays = 0.70,
    		lambdaFavorites = 0.30,
    		playRelevance = lambdaPlays * this.stats.playRelevance,
    		favRelevance = lambdaFavorites * this.stats.favoriteRelevance;
    		//console.log(playRelevance, favRelevance);
    	this.stats.relevance = (playRelevance + favRelevance) * this.stats.querySimilarity;
	}
};

module.exports = {
	SearchResult: SearchResult
}

var _ = require('underscore')._;

function SearchResult(options) {
	_.extend(this, _.pick(options,
		'url', 'permalink', 'siteMediaID',
		'siteCode', 'icon', 'author',
		'mediaName', 'duration', 'type'));
	var stats = {querySimilarity: 1, playRelevance: 1, favoriteRelevance: 1, relevance: 0.5};
	stats = _.extend(stats, _.pick(options, 'plays', 'favorites'));
	stats.plays = parseInt(stats.plays) || 0;
	stats.favorites = parseInt(stats.favorites) || 0;
	stats.querySimilarity = 1;
	stats.playRelevance = 1;
	stats.favoriteRelevance = 1;
	this.stats = stats;
}

SearchResult.prototype = {
	calculateRelevance: function() {
    	var lambdaPlays = 0.70,
    		lambdaFavorites = 0.30,
    		playRelevance = lambdaPlays * this.stats.playRelevance,
    		favRelevance = lambdaFavorites * this.stats.favoriteRelevance;
    		//console.log(playRelevance, favRelevance);
    	this.stats.relevance = (playRelevance + favRelevance) * this.stats.querySimilarity;
	}
};

module.exports = {
	SearchResult: SearchResult
}

Fix search sorting so that a search result never has "undefined" plays or favorities. This could break sorting in unexpected ways. E.g. Katy Perry shows plays but favorites on YouTube. It is better to simply avoid the use of undefined variables.


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

// Environment variables
const node_env = process.env.NODE_ENV || "Local";
const env_var = process.env.ENV_VAR || "Local";
const env_color = process.env.ENV_COLOR || "DodgerBlue";

const env = {
  NODE_ENV: node_env,
  ENV_VAR: env_var,
  ENV_COLOR: env_color
};

app.set('port', (env.PORT || 5000));

app.use(express.static(__dirname + '/dist'));

app.get('/api/getEnvironment', function(request, response){
  const envVar = {
    name: env.ENV_VAR,
    color: env.ENV_COLOR
  };

  response.json(envVar);
});

app.get('/*', function(req, res) {
  res.sendFile(path.join(__dirname + '/dist/index.html'));
});

app.listen(app.get('port'), function(){
	console.log('Node app is running on port', app.get('port'));
  console.log('NODE_ENV: '+ env.NODE_ENV);
});

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

// Environment variables
const node_env = process.env.NODE_ENV || "Local";
const env_var = process.env.ENV_VAR || "Local";
const env_color = process.env.ENV_COLOR || "DodgerBlue";

const env = {
  NODE_ENV: node_env,
  ENV_VAR: env_var,
  ENV_COLOR: env_color
};

app.set('port', (process.env.PORT || 5000));

app.use(express.static(__dirname + '/dist'));

var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();

app.get('/api/getEnvironment', function(request, response){
  const envVar = {
    name: env.ENV_VAR,
    color: env.ENV_COLOR
  };

  response.json(envVar);
});

app.get('/*', function(req, res) {
  res.sendFile(path.join(__dirname + '/dist/index.html'));
});

app.listen(app.get('port'), function(){
	console.log('Node app is running on port', app.get('port'));
  console.log('NODE_ENV: '+ process.env.NODE_ENV);
});

Test fix for node crash


var babylon = require("babylon");

exports.options = {
  sourceType: "module",
  strictMode: false,
  allowImportExportEverywhere: true,
  allowReturnOutsideFunction: true,
  plugins: [
    "asyncFunctions",
    "asyncGenerators",
    "classConstructorCall",
    "classProperties",
    "decorators",
    "doExpressions",
    "exponentiationOperator",
    "exportExtensions",
    "flow",
    "functionBind",
    "functionSent",
    "jsx",
    "objectRestSpread",
    "trailingFunctionCommas"
  ]
};

function babylonParse(code) {
  return babylon.parse(code, exports.options);
}

exports.parse = babylonParse;

var babylon = require("babylon");

exports.options = {
  sourceType: "module",
  strictMode: false,
  allowImportExportEverywhere: true,
  allowReturnOutsideFunction: true,
  plugins: ["*", "jsx", "flow"]
};

function babylonParse(code) {
  return babylon.parse(code, exports.options);
}

exports.parse = babylonParse;

Enable all Acorn plugins using wildcard.


var gpio = require('onoff').Gpio;
var red = new gpio(16, 'out');
var green = new gpio(12, 'out');
var blue = new gpio(21, 'out');
var button = new gpio(25, 'in', 'both');
var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('Hi I changed this again!');
});

app.listen(3000, function(){
  console.log('App listening on port 3000!');
})
// define the callback function
function light(err, state) {

  console.log('Button pushed');

  // check the state of the button
  // 1 == pressed, 0 == not pressed
  if(state == 1) {
    // turn LED on
    red.writeSync(1);
    gree.writeSync(1);
    blue.writeSync(1);
  } else {
    // turn LED off
    red.writeSync(0);
    gree.writeSync(0);
    blue.writeSync(0)
  }

}

// pass the callback function to the
// as the first argument to watch()
button.watch(light);

var gpio = require('onoff').Gpio;
var red = new gpio(16, 'out');
var green = new gpio(12, 'out');
var blue = new gpio(21, 'out');
var button = new gpio(25, 'in', 'both');
var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('Hi I changed this again!');
});

app.listen(3001, function(){
  console.log('App listening on port 3001!');
})
// define the callback function
function light(err, state) {

  console.log('Button pushed');

  // check the state of the button
  // 1 == pressed, 0 == not pressed
  if(state == 1) {
    // turn LED on
    red.writeSync(1);
    gree.writeSync(1);
    blue.writeSync(1);
  } else {
    // turn LED off
    red.writeSync(0);
    gree.writeSync(0);
    blue.writeSync(0)
  }

}

// pass the callback function to the
// as the first argument to watch()
button.watch(light);

Change port for testing purposes


var Filter = require('broccoli-filter')

module.exports = CoffeeScriptFilter
CoffeeScriptFilter.prototype = Object.create(Filter.prototype)
CoffeeScriptFilter.prototype.constructor = CoffeeScriptFilter
function CoffeeScriptFilter (inputTree, options) {
  if (!(this instanceof CoffeeScriptFilter)) return new CoffeeScriptFilter(inputTree, options)
  this.inputTree = inputTree
  this.options = options || {}
}

CoffeeScriptFilter.prototype.extensions = ['coffee']
CoffeeScriptFilter.prototype.targetExtension = 'js'

CoffeeScriptFilter.prototype.processString = function (string) {
  // We must be careful to create a fresh options hash every time.
  // https://github.com/jashkenas/coffee-script/issues/1924#issuecomment-28157026
  var options = {
    bare: this.options.bare
  }
  try {
    return require('coffee-script').compile(string, options)
  } catch (err) {
    err.line = err.location && err.location.first_line
    err.column = err.location && err.location.first_column
    throw err
  }
}

var Filter = require('broccoli-filter')
var coffeeScript = require('coffee-script')

module.exports = CoffeeScriptFilter
CoffeeScriptFilter.prototype = Object.create(Filter.prototype)
CoffeeScriptFilter.prototype.constructor = CoffeeScriptFilter
function CoffeeScriptFilter (inputTree, options) {
  if (!(this instanceof CoffeeScriptFilter)) return new CoffeeScriptFilter(inputTree, options)
  Filter.call(this, inputTree, options)
  this.bare = options && options.bare
}

CoffeeScriptFilter.prototype.extensions = ['coffee']
CoffeeScriptFilter.prototype.targetExtension = 'js'

CoffeeScriptFilter.prototype.processString = function (string) {
  var coffeeScriptOptions = { bare: this.bare }
  try {
    return coffeeScript.compile(string, coffeeScriptOptions)
  } catch (err) {
    err.line = err.location && err.location.first_line
    err.column = err.location && err.location.first_column
    throw err
  }
}

Call Filter constructor to allow for common Filter options


Update cache busting for rps.masonry


var express = require('express');
var RedisStore = require('connect-redis')(express);
var routes = require('./routes');
var url = require('url');
var whiskers = require('whiskers');

var port = process.env.PORT || 8127;
var redisUrl = process.env.REDISTOGO_URL &&
  url.parse(process.env.REDISTOGO_URL);
var redisOptions = redisUrl && {
  host: redisUrl.hostname,
  port: redisUrl.port,
  pass: redisUrl.auth.split(':')[1]
};

var app = express();
app.engine('.html', whiskers.__express);
app.set('views', __dirname + '/templates');

app.use('/api', express.query());
app.use(express.logger());
app.use(express.cookieParser('walrus'));
app.use(express.session({
  store: new RedisStore(redisOptions),
  secret: process.env.SECRET || 'walrus'
}));
app.use(app.router);
app.use(express.staticCache());
app.use(express.static(__dirname + '/static', {maxAge: 86400000}));

routes(app);

app.listen(port);
console.log('Running on port '+port);

var express = require('express');
var RedisStore = require('connect-redis')(express);
var routes = require('./routes');
var url = require('url');
var whiskers = require('whiskers');

var port = process.env.PORT || process.argv[2] || 8127;
var redisUrl = process.env.REDISTOGO_URL &&
  url.parse(process.env.REDISTOGO_URL);
var redisOptions = redisUrl && {
  host: redisUrl.hostname,
  port: redisUrl.port,
  pass: redisUrl.auth.split(':')[1]
};

var app = express();
app.engine('.html', whiskers.__express);
app.set('views', __dirname + '/templates');

app.use('/api', express.query());
app.use(express.logger());
app.use(express.cookieParser('walrus'));
app.use(express.session({
  store: new RedisStore(redisOptions),
  secret: process.env.SECRET || 'walrus'
}));
app.use(app.router);
app.use(express.staticCache());
app.use(express.static(__dirname + '/static', {maxAge: 86400000}));

routes(app);

app.listen(port);
console.log('Running on port '+port);

Allow port to be passed in as argv


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

/**
 * Looks for files with .html, .hbs, or .handlebars extensions within the given directory, and adds them as Handlebars partials matching the name of the file.
 * @param {string} dir - Folder to check for partials.
 */
module.exports = function(dir) {
  var partials = glob.sync(path.join(dir, '**/*.{html,hbs,handlebars}'));

  for (var i in partials) {
    var file = fs.readFileSync(partials[i]);
    var name = path.basename(partials[i], '.html');
    this.Handlebars.registerPartial(name, file.toString() + '\n');
  }
}

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

/**
 * Looks for files with .html, .hbs, or .handlebars extensions within the given directory, and adds them as Handlebars partials matching the name of the file.
 * @param {string} dir - Folder to check for partials.
 */
module.exports = function(dir) {
  var partials = glob.sync(path.join(dir, '**/*.{html,hbs,handlebars}'));

  for (var i in partials) {
    var ext = path.extname(partials[i]);
    var file = fs.readFileSync(partials[i]);
    var name = path.basename(partials[i], ext);
    this.Handlebars.registerPartial(name, file.toString() + '\n');
  }
}

Fix loading of partials according to generic file extension.


var AppSpec = function(appDir, runAs, prefix, logDir, settings) {
  this.appDir = appDir;
  this.runAs = runAs;
  this.prefix = prefix;
  this.logDir = logDir;
  this.settings = settings;
};
module.exports = AppSpec;

(function() {

  this.getKey = function() {
    JSON.stringify(this);
  };

}).call(AppSpec.prototype);

var AppSpec = function(appDir, runAs, prefix, logDir, settings) {
  this.appDir = appDir;
  this.runAs = runAs;
  this.prefix = prefix;
  this.logDir = logDir;
  this.settings = settings;
};
module.exports = AppSpec;

(function() {

  this.getKey = function() {
    return this.appDir + "\n" +
      this.runAs + "\n" +
      this.prefix + "\n" +
      this.logDir + "\n" +
      JSON.stringify(this.settings);
  };

}).call(AppSpec.prototype);

Use correct logic to form AppSpec key


const Discord = require('discord.js');
const client = new Discord.Client();
const _ = require('lodash');
const winston = require('winston');

require('dotenv').config();

const channel_handler = require('./channel_handler');
const presence_handler = require('./presence_handler');

winston.configure({
  transports: [
    new (winston.transports.Console)({
      timestamp: true,
    }),
    new (winston.transports.File)({
      filename: 'sgs_bot.log',
    }),
  ],
});

client.on('ready', () => {
  winston.log('info', 'Logged into Discord as %s', client.user.tag);
  // set creepy presence
  client.user.setPresence({
    status: 'online',
    afk: false,
    game: {
      name: 'Big Brother',
      url: '',
    },
  });
});

client.on('presenceUpdate', presence_handler.handlePresenceUpdate);
client.on('voiceStateUpdate', channel_handler.handleVoiceStateUpdate);

client.login('MzMwMDgzODQ2NzQzNjU0NDAx.DDb8_A.Aq9f9KnUQq4Hu_oqVxxULnS5BUY');

const Discord = require('discord.js');
const client = new Discord.Client();
const _ = require('lodash');
const winston = require('winston');

require('dotenv').config();

const channel_handler = require('./channel_handler');
const presence_handler = require('./presence_handler');

winston.configure({
  transports: [
    new (winston.transports.Console)({
      timestamp: true,
    }),
    new (winston.transports.File)({
      filename: 'sgs_bot.log',
    }),
  ],
});

client.on('ready', () => {
  winston.log('info', 'Logged into Discord as %s', client.user.tag);
  // set creepy presence
  client.user.setPresence({
    status: 'online',
    afk: false,
    game: {
      name: 'Big Brother',
      url: '',
    },
  });
});

client.on('presenceUpdate', presence_handler.handlePresenceUpdate);
client.on('voiceStateUpdate', channel_handler.handleVoiceStateUpdate);

client.login(process.env.DISCORD_KEY);

Use the config for token


'use strict';

module.exports = {
	rules: {
		'arrow-parens': ['error', 'always'],
		'object-curly-spacing': ['error', 'always']
	}
};

'use strict';

module.exports = {
	rules: {
		'arrow-parens': ['error', 'always'],
		'brace-style': ['error', 'stroustrup'],
		'capitalized-comments': 'warning',
		'generator-star-spacing': ['error', 'after'],
		'object-curly-spacing': ['error', 'always']
	}
};

Add a couple rule overrides


var osx   = process.platform === 'darwin'
var win   = process.platform === 'win32'
var other = !osx && !win
var fs    = require('fs')

if (other) {
  try {
    module.exports = require('which').sync('firefox')
  } catch (_) {
    module.exports = null
  }

} else
if (osx) {
  var regPath = '/Applications/Firefox.app/Contents/MacOS/firefox'
  var altPath = require('userhome')(regPath.slice(1))

  module.exports = fs.existsSync(regPath)
    ? regPath
    : altPath
} else {
  var suffix = '\\Mozilla Firefox\\firefox.exe';
  var prefixes = [
      process.env.LOCALAPPDATA
    , process.env.PROGRAMFILES
    , process.env['PROGRAMFILES(X86)']
  ]

  for (var i = 0; i < prefixes.length; i++) {
    var exe = prefixes[i] + suffix
    if (fs.existsSync(exe)) {
      module.exports = exe
      break
    }
  }

  module.exports = module.exports || null
}

var osx   = process.platform === 'darwin'
var win   = process.platform === 'win32'
var other = !osx && !win
var fs    = require('fs')

if (other) {
  try {
    module.exports = require('which').sync('firefox')
  } catch (_) {
    module.exports = null
  }

} else
if (osx) {
  var regPath = '/Applications/Firefox.app/Contents/MacOS/firefox'
  var altPath = require('userhome')(regPath.slice(1))

  module.exports = fs.existsSync(regPath)
    ? regPath
    : altPath
} else {
  var suffix = '\\Mozilla Firefox\\firefox.exe'
  module.exports = [
      process.env.LOCALAPPDATA
    , process.env.PROGRAMFILES
    , process.env['PROGRAMFILES(X86)']
  ].reduce(function (existing, prefix) {
    var exe = prefix + suffix
    return existing || fs.existsSync(exe) ? exe : null
  }, null)
}

Return null when Firefox is not found on Windows


module.exports = {
	extends: ['airbnb'],
	env: {
		browser: false,
	},
	plugins: ['filenames'],
	rules: {
		// Use tab for indentation http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/
		indent: [2, 'tab'],
		// allow anonymous functions
		'func-names': 0,
		// Enforce that filenames are camelcase
		'filenames/filenames': 2,
		// Prevent missing displayName in a React component definition
		'react/display-name': 2,
		// Prevent duplicate props in JSX
		'react/jsx-no-duplicate-props': 2,
	},
};

module.exports = {
	extends: ['airbnb'],
	env: {
		browser: false,
	},
	plugins: ['filenames'],
	rules: {
		// Use tab for indentation http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/
		indent: [2, 'tab'],
		// allow anonymous functions
		'func-names': 0,
		// Enforce that filenames are camelcase
		'filenames/filenames': [2, "^[a-z\-]+$"],
		// Prevent missing displayName in a React component definition
		'react/display-name': 2,
		// Prevent duplicate props in JSX
		'react/jsx-no-duplicate-props': 2,
	},
};

Change filename rule to all lowercase and dashes


var postcss = require('postcss'),
    mime = require('mime'),
    fs = require('fs');

module.exports = postcss.plugin('postcss-data-uri', function (opts) {
    return function (css) {
        css.walkDecls(/background(\-image)?/i, function (decl) {
            var rePattern = /data-uri\(\s*['|"]?(.*?)['|"]?\s*\)/i,
                path;

            if (rePattern.test(decl.value)) {
                path = decl.value.match(rePattern)[1];
                if (fs.existsSync(path)) {
                    decl.value = decl.value.replace(rePattern, 'url(data:' + mime.lookup(path) + ';base64,' + new Buffer(fs.readFileSync(path)).toString('base64') + ')');
                } else {
                    console.log('Image ',path,' not found.')
                }
            }
        });
    };
});

var postcss = require('postcss'),
    mime = require('mime'),
    fs = require('fs');

module.exports = postcss.plugin('postcss-data-uri', function (opts) {
    return function (css) {
        css.walkDecls(/background(\-image)?/i, function (decl) {
            var rePattern = /data-uri\(\s*['|"]?(.*?)['|"]?\s*\)/i,
                path;

            if (rePattern.test(decl.value)) {
                path = decl.value.match(rePattern)[1];
                if (fs.existsSync(path)) {
                    decl.value = decl.value.replace(rePattern, 'url(data:' + mime.lookup(path) + ';base64,' + fs.readFileSync(path, 'base64') + ')');
                } else {
                    console.log('Image ',path,' not found.')
                }
            }
        });
    };
});

Use fs.readSync's options to get base64 string


require( 'dotenv' ).config();
var dropboxModule = require( './modules/dropbox.js' );
var googleDocsModule = require( './modules/googleDocs.js' );
var paypalModule = require( './modules/paypal.js' );
var express = require( 'express' );
var app = express();

app.set( 'port', ( process.env.Port ) );
app.use( express.static( __dirname + '/public' ) );

app.get( '/googleapitoken', function( request, response ) {
  googleDocsModule.googleAPIAuthorize( request, response );
});

app.get( '/trigger', function( request, response ) {
  googleDocsModule.verifySecrets()
  .then(function( res ) {
    console.log( 'Application verified! Fetching PayPal rate.' );
    paypalModule.fetchPaypalRate();
    response.send( 'Triggered!' );
  })
  .catch(function( error ) {
    var errorMessage = 'Failed to authenticate! (' + error + ')';
    console.log( errorMessage );
    response.send( errorMessage );
  });
});

app.listen( app.get( 'port' ), function() {
  console.log( 'Node app is running at localhost:' + app.get( 'port' ) );
});

require( 'dotenv' ).config();
var dropboxModule = require( './modules/dropbox.js' );
var googleDocsModule = require( './modules/googleDocs.js' );
var paypalModule = require( './modules/paypal.js' );
var express = require( 'express' );
var app = express();

app.set( 'port', ( process.env.Port || 30000 ) );
app.use( express.static( __dirname + '/public' ) );

app.get( '/googleapitoken', function( request, response ) {
  googleDocsModule.googleAPIAuthorize( request, response );
});

app.get( '/trigger', function( request, response ) {
  googleDocsModule.verifySecrets()
  .then(function( res ) {
    console.log( 'Application verified! Fetching PayPal rate.' );
    paypalModule.fetchPaypalRate();
    response.send( 'Triggered!' );
  })
  .catch(function( error ) {
    var errorMessage = 'Failed to authenticate! (' + error + ')';
    console.log( errorMessage );
    response.send( errorMessage );
  });
});

app.listen( app.get( 'port' ), function() {
  console.log( 'Node app is running at localhost:' + app.get( 'port' ) );
});

Fix an issue with the port number


'use strict'

module.exports = {
    globalize: require('./src/globalize'),
    toUpperLowerCase: require('./src/toUpperLowerCase'),
    substituir: require('./src/substituir'),
    dataHora: require('./src/dataHora'),
    chaveUnica: require('./src/chaveUnica'),
    ajaxSubmit: require('./src/ajaxSubmit'),
    verificaErro: require('./src/verificaErro'),
    isCPF: require('./src/isCPF'),
    teste: "sei la"
}

'use strict'

module.exports = {
    globalize: require('./src/globalize'),
    toUpperLowerCase: require('./src/toUpperLowerCase'),
    substituir: require('./src/substituir'),
    dataHora: require('./src/dataHora'),
    chaveUnica: require('./src/chaveUnica'),
    ajaxSubmit: require('./src/ajaxSubmit'),
    verificaErro: require('./src/verificaErro'),
    isCPF: require('./src/isCPF')
}

Rollback do teste de alteração do Bower.


var koa = require('koa');
var route = require('koa-route');
var logger = require('koa-logger');
var app = koa();
var debug = require('debug')('index')
var intents = require('./controllers/intents');
var adManifest = require('./controllers/ad-manifest');
var sync = require('./controllers/sync');

app.use(logger());

app.use(route.get('/', function * () {
	this.body = 'Welcome to the Vault.';
}));
app.use(route.get('/ad-manifest', adManifest.get));
app.use(route.post('/intents', intents.push));
app.use(route.get('/sync/:userId', sync.get));
app.use(route.post('/sync', sync.push));

app.listen(3000, function() {
  debug('webserver started at http://localhost:3000');
});

app.on('error', function(err){
  debug('server error', err);
});

var koa = require('koa');
var route = require('koa-route');
var logger = require('koa-logger');
var app = koa();
var debug = require('debug')('index')
var intents = require('./controllers/intents');
var adManifest = require('./controllers/ad-manifest');
var sync = require('./controllers/sync');

var PORT = process.env.PORT || 3000;

app.use(logger());

app.use(route.get('/', function * () {
  this.body = 'Welcome to the Vault.';
}));
app.use(route.get('/ad-manifest', adManifest.get));
app.use(route.post('/intents', intents.push));
app.use(route.get('/sync/:userId', sync.get));
app.use(route.post('/sync', sync.push));

app.listen(PORT, function() {
  debug('webserver started on port 3000');
});

app.on('error', function(err){
  debug('server error', err);
});

Use port from environment define.


/*jslint node: true */
"use strict";

var isEmpty = function (obj) {
    return Object.keys(obj).length === 0;
}

_.isEmpty

/*jslint node: true */
"use strict";

var _ = require('underscore');
var Promise = require('bluebird');

var eventTree = function () {
    return {
        hash: {}
        , funcs: []
        , promises: []
    };
};

var addCallback = function (route, tree, cb) {
    var head = _.head(route);
    if (!tree.hash.hasOwnProperty(head)) {
        tree.hash[head] = eventTree();
    }

    if (route.length > 1) {
        return addCallback(_.rest(route), tree.hash[head], cb);
    }
    else if (route.length === 1) {
        tree.hash[head].funcs.push(cb);
    }
};

var execCallbacks = function (route, tree, msg) {
    var head = _.head(route);
    if (tree.hash.hasOwnProperty(head)) {
        if (route.length > 1) {
            return execCallbacks(_.rest(route), tree.hash[head], msg);
        }
        else if (route.length === 1) {
            return new Promise(function (resolve, reject) {
                _.each(tree.hash[head].funcs, function (cb) {
                    cb(msg);
                });
                return resolve(true);
            });
        }
    }
    else {
        return new Promise(function (resolve, reject) {
            return resolve(false);
        });
    }
};

var removeCallback = function (route, tree, f) {
    var head = _.head(route);
    if (tree.hash.hasOwnProperty(head)) {
        if (route.length > 1) {
            return removeCallback(_.rest(route), tree.hash[head], f);
        }
        else if (route.length === 1) {
            tree.hash[head].funcs = _.without(tree.hash[head].funcs, f);
        }
    }
};

var EventEmitter = function () {
    this._eventTree = eventTree();
};

_.extend(EventEmitter.prototype, {
    on: function (route, cb) {
        return addCallback(route, this._eventTree, cb);
    }
    , emit: function (route, msg) {
        return execCallbacks(route, this._eventTree, msg);
    }
    , removeListener: function (route, f) {
        return removeCallback(route, this._eventTree, f);
    }
});

module.exports = {
    EventEmitter: EventEmitter
};

Add a preliminary version without wildcards or promises.


// Internet Icon by Freepik (http://www.flaticon.com/free-icon/worldwide_448589)

const urlencode = require('urlencode');

module.exports = {
    action: 'openurl',
    query: (query) => {
        const items = [];
        const searchTerm = query.slice(6);
        const url = 'https:\/\/www.google.com/search?q=' + urlencode(searchTerm);
        items.push({
            title: `Search Google for ${searchTerm}`,
            subtitle: 'Open in browser',
            arg: url,
            icon: {
                path: './icon.png'
            }
        });
        return { items };
    }
};

// Internet Icon by Freepik (http://www.flaticon.com/free-icon/worldwide_448589)

const urlencode = require('urlencode');

module.exports = {
    action: 'openurl',
    query: (query) => {
        const items = [];
        const searchTerm = query.slice(0);
        const url = 'https:\/\/www.google.com/search?q=' + urlencode(searchTerm);
        items.push({
            title: `Search Google for ${searchTerm}`,
            subtitle: 'Open in browser',
            arg: url,
            icon: {
                path: './icon.png'
            }
        });
        return { items };
    }
};

Fix the cutting out of the first 6 chars