Index: frontend/node_modules/utila/.npmignore
===================================================================
--- frontend/node_modules/utila/.npmignore	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/.npmignore	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,10 @@
+*.bat
+.htaccess
+
+src
+
+npm-debug.log
+!*.gitkeep
+
+node_modules
+xeno
Index: frontend/node_modules/utila/LICENSE
===================================================================
--- frontend/node_modules/utila/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Aria Minaei
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: frontend/node_modules/utila/README.md
===================================================================
--- frontend/node_modules/utila/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,7 @@
+notareplacementforunderscore
+
+# Installation
+
+**npm**: `npm install utila`
+
+**bower**: available via bower as in `bower install utila`, but you should run `npm install` before you can use it.
Index: frontend/node_modules/utila/lib/Emitter.js
===================================================================
--- frontend/node_modules/utila/lib/Emitter.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/Emitter.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,137 @@
+// Generated by CoffeeScript 1.6.3
+var Emitter, array;
+
+array = require('./array');
+
+module.exports = Emitter = (function() {
+  function Emitter() {
+    this._listeners = {};
+    this._listenersForAnyEvent = [];
+    this._disabledEmitters = {};
+  }
+
+  Emitter.prototype.on = function(eventName, listener) {
+    if (this._listeners[eventName] == null) {
+      this._listeners[eventName] = [];
+    }
+    this._listeners[eventName].push(listener);
+    return this;
+  };
+
+  Emitter.prototype.once = function(eventName, listener) {
+    var cb, ran,
+      _this = this;
+    ran = false;
+    cb = function() {
+      if (ran) {
+        return;
+      }
+      ran = true;
+      listener();
+      return setTimeout(function() {
+        return _this.removeEvent(eventName, cb);
+      }, 0);
+    };
+    this.on(eventName, cb);
+    return this;
+  };
+
+  Emitter.prototype.onAnyEvent = function(listener) {
+    this._listenersForAnyEvent.push(listener);
+    return this;
+  };
+
+  Emitter.prototype.removeEvent = function(eventName, listener) {
+    if (this._listeners[eventName] == null) {
+      return this;
+    }
+    array.pluckOneItem(this._listeners[eventName], listener);
+    return this;
+  };
+
+  Emitter.prototype.removeListeners = function(eventName) {
+    if (this._listeners[eventName] == null) {
+      return this;
+    }
+    this._listeners[eventName].length = 0;
+    return this;
+  };
+
+  Emitter.prototype.removeAllListeners = function() {
+    var listeners, name, _ref;
+    _ref = this._listeners;
+    for (name in _ref) {
+      listeners = _ref[name];
+      listeners.length = 0;
+    }
+    return this;
+  };
+
+  Emitter.prototype._emit = function(eventName, data) {
+    var listener, _i, _j, _len, _len1, _ref, _ref1;
+    _ref = this._listenersForAnyEvent;
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      listener = _ref[_i];
+      listener.call(this, data, eventName);
+    }
+    if (this._listeners[eventName] == null) {
+      return;
+    }
+    _ref1 = this._listeners[eventName];
+    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+      listener = _ref1[_j];
+      listener.call(this, data);
+    }
+  };
+
+  Emitter.prototype._throttleEmitterMethod = function(fnName, time) {
+    var lastCallArgs, originalFn, pend, pending, runIt, timer,
+      _this = this;
+    if (time == null) {
+      time = 1000;
+    }
+    originalFn = this[fnName];
+    if (typeof originalFn !== 'function') {
+      throw Error("this class does not have a method called '" + fnName + "'");
+    }
+    lastCallArgs = null;
+    pending = false;
+    timer = null;
+    this[fnName] = function() {
+      lastCallArgs = arguments;
+      return pend();
+    };
+    pend = function() {
+      if (pending) {
+        clearTimeout(timer);
+      }
+      timer = setTimeout(runIt, time);
+      return pending = true;
+    };
+    return runIt = function() {
+      pending = false;
+      return originalFn.apply(_this, lastCallArgs);
+    };
+  };
+
+  Emitter.prototype._disableEmitter = function(fnName) {
+    if (this._disabledEmitters[fnName] != null) {
+      throw Error("" + fnName + " is already a disabled emitter");
+    }
+    this._disabledEmitters[fnName] = this[fnName];
+    return this[fnName] = function() {};
+  };
+
+  Emitter.prototype._enableEmitter = function(fnName) {
+    var fn;
+    fn = this._disabledEmitters[fnName];
+    if (fn == null) {
+      throw Error("" + fnName + " is not a disabled emitter");
+    }
+    this[fnName] = fn;
+    return delete this._disabledEmitters[fnName];
+  };
+
+  return Emitter;
+
+})();
Index: frontend/node_modules/utila/lib/_common.js
===================================================================
--- frontend/node_modules/utila/lib/_common.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/_common.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,111 @@
+// Generated by CoffeeScript 1.6.3
+var common;
+
+module.exports = common = {
+  /*
+  	Checks to see if o is an object, and it isn't an instance
+  	of some class.
+  */
+
+  isBareObject: function(o) {
+    if ((o != null) && o.constructor === Object) {
+      return true;
+    }
+    return false;
+  },
+  /*
+  	Returns type of an object, including:
+  	undefined, null, string, number, array,
+  	arguments, element, textnode, whitespace, and object
+  */
+
+  typeOf: function(item) {
+    var _ref;
+    if (item === null) {
+      return 'null';
+    }
+    if (typeof item !== 'object') {
+      return typeof item;
+    }
+    if (Array.isArray(item)) {
+      return 'array';
+    }
+    if (item.nodeName) {
+      if (item.nodeType === 1) {
+        return 'element';
+      }
+      if (item.nodeType === 3) {
+        return (_ref = /\S/.test(item.nodeValue)) != null ? _ref : {
+          'textnode': 'whitespace'
+        };
+      }
+    } else if (typeof item.length === 'number') {
+      if (item.callee) {
+        return 'arguments';
+      }
+    }
+    return typeof item;
+  },
+  clone: function(item, includePrototype) {
+    if (includePrototype == null) {
+      includePrototype = false;
+    }
+    switch (common.typeOf(item)) {
+      case 'array':
+        return common._cloneArray(item, includePrototype);
+      case 'object':
+        return common._cloneObject(item, includePrototype);
+      default:
+        return item;
+    }
+  },
+  /*
+  	Deep clone of an object.
+  	From MooTools
+  */
+
+  _cloneObject: function(o, includePrototype) {
+    var clone, key;
+    if (includePrototype == null) {
+      includePrototype = false;
+    }
+    if (common.isBareObject(o)) {
+      clone = {};
+      for (key in o) {
+        clone[key] = common.clone(o[key], includePrototype);
+      }
+      return clone;
+    } else {
+      if (!includePrototype) {
+        return o;
+      }
+      if (o instanceof Function) {
+        return o;
+      }
+      clone = Object.create(o.constructor.prototype);
+      for (key in o) {
+        if (o.hasOwnProperty(key)) {
+          clone[key] = common.clone(o[key], includePrototype);
+        }
+      }
+      return clone;
+    }
+  },
+  /*
+  	Deep clone of an array.
+  	From MooTools
+  */
+
+  _cloneArray: function(a, includePrototype) {
+    var clone, i;
+    if (includePrototype == null) {
+      includePrototype = false;
+    }
+    i = a.length;
+    clone = new Array(i);
+    while (i--) {
+      clone[i] = common.clone(a[i], includePrototype);
+    }
+    return clone;
+  }
+};
Index: frontend/node_modules/utila/lib/array.js
===================================================================
--- frontend/node_modules/utila/lib/array.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/array.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,165 @@
+// Generated by CoffeeScript 1.6.3
+var array;
+
+module.exports = array = {
+  /*
+  	Tries to turn anything into an array.
+  */
+
+  from: function(r) {
+    return Array.prototype.slice.call(r);
+  },
+  /*
+  	Clone of an array. Properties will be shallow copies.
+  */
+
+  simpleClone: function(a) {
+    return a.slice(0);
+  },
+  shallowEqual: function(a1, a2) {
+    var i, val, _i, _len;
+    if (!(Array.isArray(a1) && Array.isArray(a2) && a1.length === a2.length)) {
+      return false;
+    }
+    for (i = _i = 0, _len = a1.length; _i < _len; i = ++_i) {
+      val = a1[i];
+      if (a2[i] !== val) {
+        return false;
+      }
+    }
+    return true;
+  },
+  pluck: function(a, i) {
+    var index, value, _i, _len;
+    if (a.length < 1) {
+      return a;
+    }
+    for (index = _i = 0, _len = a.length; _i < _len; index = ++_i) {
+      value = a[index];
+      if (index > i) {
+        a[index - 1] = a[index];
+      }
+    }
+    a.length = a.length - 1;
+    return a;
+  },
+  pluckItem: function(a, item) {
+    var index, removed, value, _i, _len;
+    if (a.length < 1) {
+      return a;
+    }
+    removed = 0;
+    for (index = _i = 0, _len = a.length; _i < _len; index = ++_i) {
+      value = a[index];
+      if (value === item) {
+        removed++;
+        continue;
+      }
+      if (removed !== 0) {
+        a[index - removed] = a[index];
+      }
+    }
+    if (removed > 0) {
+      a.length = a.length - removed;
+    }
+    return a;
+  },
+  pluckOneItem: function(a, item) {
+    var index, reached, value, _i, _len;
+    if (a.length < 1) {
+      return a;
+    }
+    reached = false;
+    for (index = _i = 0, _len = a.length; _i < _len; index = ++_i) {
+      value = a[index];
+      if (!reached) {
+        if (value === item) {
+          reached = true;
+          continue;
+        }
+      } else {
+        a[index - 1] = a[index];
+      }
+    }
+    if (reached) {
+      a.length = a.length - 1;
+    }
+    return a;
+  },
+  pluckByCallback: function(a, cb) {
+    var index, removed, value, _i, _len;
+    if (a.length < 1) {
+      return a;
+    }
+    removed = 0;
+    for (index = _i = 0, _len = a.length; _i < _len; index = ++_i) {
+      value = a[index];
+      if (cb(value, index)) {
+        removed++;
+        continue;
+      }
+      if (removed !== 0) {
+        a[index - removed] = a[index];
+      }
+    }
+    if (removed > 0) {
+      a.length = a.length - removed;
+    }
+    return a;
+  },
+  pluckMultiple: function(array, indexesToRemove) {
+    var i, removedSoFar, _i, _len;
+    if (array.length < 1) {
+      return array;
+    }
+    removedSoFar = 0;
+    indexesToRemove.sort();
+    for (_i = 0, _len = indexesToRemove.length; _i < _len; _i++) {
+      i = indexesToRemove[_i];
+      this.pluck(array, i - removedSoFar);
+      removedSoFar++;
+    }
+    return array;
+  },
+  injectByCallback: function(a, toInject, shouldInject) {
+    var i, len, val, valA, valB, _i, _len;
+    valA = null;
+    valB = null;
+    len = a.length;
+    if (len < 1) {
+      a.push(toInject);
+      return a;
+    }
+    for (i = _i = 0, _len = a.length; _i < _len; i = ++_i) {
+      val = a[i];
+      valA = valB;
+      valB = val;
+      if (shouldInject(valA, valB, toInject)) {
+        return a.splice(i, 0, toInject);
+      }
+    }
+    a.push(toInject);
+    return a;
+  },
+  injectInIndex: function(a, index, toInject) {
+    var i, len, toPut, toPutNext;
+    len = a.length;
+    i = index;
+    if (len < 1) {
+      a.push(toInject);
+      return a;
+    }
+    toPut = toInject;
+    toPutNext = null;
+    for(; i <= len; i++){
+
+			toPutNext = a[i];
+
+			a[i] = toPut;
+
+			toPut = toPutNext;
+
+		};
+    return null;
+  }
+};
Index: frontend/node_modules/utila/lib/classic.js
===================================================================
--- frontend/node_modules/utila/lib/classic.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/classic.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,86 @@
+// Generated by CoffeeScript 1.6.3
+var classic,
+  __slice = [].slice;
+
+module.exports = classic = {};
+
+classic.implement = function() {
+  var classProto, classReference, desc, member, mixin, mixins, _i, _j, _len;
+  mixins = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), classReference = arguments[_i++];
+  for (_j = 0, _len = mixins.length; _j < _len; _j++) {
+    mixin = mixins[_j];
+    classProto = classReference.prototype;
+    for (member in mixin.prototype) {
+      if (!Object.getOwnPropertyDescriptor(classProto, member)) {
+        desc = Object.getOwnPropertyDescriptor(mixin.prototype, member);
+        Object.defineProperty(classProto, member, desc);
+      }
+    }
+  }
+  return classReference;
+};
+
+classic.mix = function() {
+  var classProto, classReference, desc, member, mixin, mixins, _i, _j, _len;
+  mixins = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), classReference = arguments[_i++];
+  classProto = classReference.prototype;
+  classReference.__mixinCloners = [];
+  classReference.__applyClonersFor = function(instance, args) {
+    var cloner, _j, _len, _ref;
+    if (args == null) {
+      args = null;
+    }
+    _ref = classReference.__mixinCloners;
+    for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+      cloner = _ref[_j];
+      cloner.apply(instance, args);
+    }
+  };
+  classReference.__mixinInitializers = [];
+  classReference.__initMixinsFor = function(instance, args) {
+    var initializer, _j, _len, _ref;
+    if (args == null) {
+      args = null;
+    }
+    _ref = classReference.__mixinInitializers;
+    for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+      initializer = _ref[_j];
+      initializer.apply(instance, args);
+    }
+  };
+  classReference.__mixinQuitters = [];
+  classReference.__applyQuittersFor = function(instance, args) {
+    var quitter, _j, _len, _ref;
+    if (args == null) {
+      args = null;
+    }
+    _ref = classReference.__mixinQuitters;
+    for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+      quitter = _ref[_j];
+      quitter.apply(instance, args);
+    }
+  };
+  for (_j = 0, _len = mixins.length; _j < _len; _j++) {
+    mixin = mixins[_j];
+    if (!(mixin.constructor instanceof Function)) {
+      throw Error("Mixin should be a function");
+    }
+    for (member in mixin.prototype) {
+      if (member.substr(0, 11) === '__initMixin') {
+        classReference.__mixinInitializers.push(mixin.prototype[member]);
+        continue;
+      } else if (member.substr(0, 11) === '__clonerFor') {
+        classReference.__mixinCloners.push(mixin.prototype[member]);
+        continue;
+      } else if (member.substr(0, 12) === '__quitterFor') {
+        classReference.__mixinQuitters.push(mixin.prototype[member]);
+        continue;
+      }
+      if (!Object.getOwnPropertyDescriptor(classProto, member)) {
+        desc = Object.getOwnPropertyDescriptor(mixin.prototype, member);
+        Object.defineProperty(classProto, member, desc);
+      }
+    }
+  }
+  return classReference;
+};
Index: frontend/node_modules/utila/lib/object.js
===================================================================
--- frontend/node_modules/utila/lib/object.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/object.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,158 @@
+// Generated by CoffeeScript 1.6.3
+var object, _common,
+  __hasProp = {}.hasOwnProperty;
+
+_common = require('./_common');
+
+module.exports = object = {
+  isBareObject: _common.isBareObject.bind(_common),
+  /*
+  	if object is an instance of a class
+  */
+
+  isInstance: function(what) {
+    return !this.isBareObject(what);
+  },
+  /*
+  	Alias to _common.typeOf
+  */
+
+  typeOf: _common.typeOf.bind(_common),
+  /*
+  	Alias to _common.clone
+  */
+
+  clone: _common.clone.bind(_common),
+  /*
+  	Empties an object of its properties.
+  */
+
+  empty: function(o) {
+    var prop;
+    for (prop in o) {
+      if (o.hasOwnProperty(prop)) {
+        delete o[prop];
+      }
+    }
+    return o;
+  },
+  /*
+  	Empties an object. Doesn't check for hasOwnProperty, so it's a tiny
+  	bit faster. Use it for plain objects.
+  */
+
+  fastEmpty: function(o) {
+    var property;
+    for (property in o) {
+      delete o[property];
+    }
+    return o;
+  },
+  /*
+  	Overrides values fomr `newValues` on `base`, as long as they
+  	already exist in base.
+  */
+
+  overrideOnto: function(base, newValues) {
+    var key, newVal, oldVal;
+    if (!this.isBareObject(newValues) || !this.isBareObject(base)) {
+      return base;
+    }
+    for (key in base) {
+      oldVal = base[key];
+      newVal = newValues[key];
+      if (newVal === void 0) {
+        continue;
+      }
+      if (typeof newVal !== 'object' || this.isInstance(newVal)) {
+        base[key] = this.clone(newVal);
+      } else {
+        if (typeof oldVal !== 'object' || this.isInstance(oldVal)) {
+          base[key] = this.clone(newVal);
+        } else {
+          this.overrideOnto(oldVal, newVal);
+        }
+      }
+    }
+    return base;
+  },
+  /*
+  	Takes a clone of 'base' and runs #overrideOnto on it
+  */
+
+  override: function(base, newValues) {
+    return this.overrideOnto(this.clone(base), newValues);
+  },
+  append: function(base, toAppend) {
+    return this.appendOnto(this.clone(base), toAppend);
+  },
+  appendOnto: function(base, toAppend) {
+    var key, newVal, oldVal;
+    if (!this.isBareObject(toAppend) || !this.isBareObject(base)) {
+      return base;
+    }
+    for (key in toAppend) {
+      if (!__hasProp.call(toAppend, key)) continue;
+      newVal = toAppend[key];
+      if (newVal === void 0) {
+        continue;
+      }
+      if (typeof newVal !== 'object' || this.isInstance(newVal)) {
+        base[key] = newVal;
+      } else {
+        oldVal = base[key];
+        if (typeof oldVal !== 'object' || this.isInstance(oldVal)) {
+          base[key] = this.clone(newVal);
+        } else {
+          this.appendOnto(oldVal, newVal);
+        }
+      }
+    }
+    return base;
+  },
+  groupProps: function(obj, groups) {
+    var def, defs, grouped, key, name, shouldAdd, val, _i, _len;
+    grouped = {};
+    for (name in groups) {
+      defs = groups[name];
+      grouped[name] = {};
+    }
+    grouped['rest'] = {};
+    top: //;
+    for (key in obj) {
+      val = obj[key];
+      shouldAdd = false;
+      for (name in groups) {
+        defs = groups[name];
+        if (!Array.isArray(defs)) {
+          defs = [defs];
+        }
+        for (_i = 0, _len = defs.length; _i < _len; _i++) {
+          def = defs[_i];
+          if (typeof def === 'string') {
+            if (key === def) {
+              shouldAdd = true;
+            }
+          } else if (def instanceof RegExp) {
+            if (def.test(key)) {
+              shouldAdd = true;
+            }
+          } else if (def instanceof Function) {
+            if (def(key)) {
+              shouldAdd = true;
+            }
+          } else {
+            throw Error('Group definitions must either\
+						be strings, regexes, or functions.');
+          }
+          if (shouldAdd) {
+            grouped[name][key] = val;
+            continue top;
+          }
+        }
+      }
+      grouped['rest'][key] = val;
+    }
+    return grouped;
+  }
+};
Index: frontend/node_modules/utila/lib/string.js
===================================================================
--- frontend/node_modules/utila/lib/string.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/string.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,14 @@
+// Generated by CoffeeScript 1.6.3
+module.exports = {
+  pad: function(n, width, z) {
+    if (z == null) {
+      z = '0';
+    }
+    n = n + '';
+    if (n.length >= width) {
+      return n;
+    } else {
+      return new Array(width - n.length + 1).join(z) + n;
+    }
+  }
+};
Index: frontend/node_modules/utila/lib/utila.js
===================================================================
--- frontend/node_modules/utila/lib/utila.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/lib/utila.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,10 @@
+// Generated by CoffeeScript 1.6.3
+var utila;
+
+module.exports = utila = {
+  array: require('./array'),
+  classic: require('./classic'),
+  object: require('./object'),
+  string: require('./string'),
+  Emitter: require('./Emitter')
+};
Index: frontend/node_modules/utila/package.json
===================================================================
--- frontend/node_modules/utila/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,25 @@
+{
+  "name": "utila",
+  "version": "0.4.0",
+  "description": "notareplacementforunderscore",
+  "main": "lib/utila.js",
+  "devDependencies": {
+    "coffee-script": "~1.6.3",
+    "little-popo": "~0.1"
+  },
+  "scripts": {
+    "prepublish": "coffee --bare --compile --output ./lib ./src"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/AriaMinaei/utila.git"
+  },
+  "keywords": [
+    "utilities"
+  ],
+  "author": "Aria Minaei",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/AriaMinaei/utila/issues"
+  }
+}
Index: frontend/node_modules/utila/test/_prepare.coffee
===================================================================
--- frontend/node_modules/utila/test/_prepare.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/test/_prepare.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,5 @@
+path = require 'path'
+
+pathToLib = path.resolve __dirname, '../lib'
+
+require('little-popo')(pathToLib)
Index: frontend/node_modules/utila/test/array.coffee
===================================================================
--- frontend/node_modules/utila/test/array.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/test/array.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,143 @@
+require './_prepare'
+
+array = mod 'array'
+
+test 'from', ->
+
+	array.from([1]).should.be.an.instanceOf Array
+	array.from([1])[0].should.equal 1
+
+# test 'clone', ->
+
+# 	a = [0, 1, 2]
+
+# 	b = array.clone a
+
+# 	b[0].should.equal 0
+# 	b[1].should.equal 1
+
+# 	b[0] = 3
+
+# 	a[0].should.equal 0
+
+test 'pluck', ->
+
+	a = [0, 1, 2, 3]
+
+	after = array.pluck a, 1
+
+	after.length.should.equal 3
+
+	after[0].should.equal 0
+	after[1].should.equal 2
+	after[2].should.equal 3
+	after.should.equal a
+
+test 'pluckMultiple', ->
+
+	a = [0, 1, 2, 3, 4, 5, 6]
+
+	array.pluckMultiple a, [0, 4, 2, 6]
+
+	a.length.should.equal 3
+	a[0].should.equal 1
+	a[1].should.equal 3
+	a[2].should.equal 5
+
+test 'pluckItem', ->
+
+	a = [0, 1, 2, 3, 2, 4, 2]
+
+	array.pluckItem a, 2
+
+	a[0].should.equal 0
+	a[1].should.equal 1
+	a[2].should.equal 3
+	a[3].should.equal 4
+
+	array.pluckItem([1], 2).length.should.equal 1
+
+
+test 'pluckOneItem', ->
+
+	a = [0, 1, 2, 3, 2, 4, 2]
+
+	array.pluckOneItem a, 2
+
+	a[0].should.equal 0
+	a[1].should.equal 1
+	a[2].should.equal 3
+	a[3].should.equal 2
+	a[4].should.equal 4
+	a[5].should.equal 2
+
+	a = [1, 2]
+
+	array.pluckOneItem a, 1
+
+	a.length.should.equal 1
+	a[0].should.equal 2
+
+	array.pluckOneItem([], 1).length.should.equal 0
+
+	array.pluckOneItem([1], 2).length.should.equal 1
+
+test 'plcukByCallback', ->
+
+	a = [0, 1, 2, 3]
+
+	array.pluckByCallback a, (val, i) ->
+
+		return yes if val is 2
+
+		return no
+
+	a[0].should.equal 0
+	a[1].should.equal 1
+	a[2].should.equal 3
+
+test 'injectByCallback', ->
+
+	shouldInject = (valA, valB, toInject) ->
+
+		unless valA?
+
+			return yes if toInject <= valB
+
+			return no
+
+		unless valB?
+
+			return yes if valA <= toInject
+
+			return no
+
+		return yes if valA <= toInject <= valB
+
+		return no
+
+	a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3]
+
+	array.injectByCallback a, 0, shouldInject
+
+	a[0].should.equal 0
+	a[1].should.equal 0.5
+	a[7].should.equal 3
+
+	a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3]
+
+	array.injectByCallback a, 2.7, shouldInject
+
+	a[0].should.equal 0.5
+	a[4].should.equal 2.7
+	a[5].should.equal 2.75
+	a[7].should.equal 3
+
+	a = [0.5, 1, 2.5, 2.5, 2.75, 2.75, 3]
+
+	array.injectByCallback a, 3.2, shouldInject
+
+	a[0].should.equal 0.5
+	a[4].should.equal 2.75
+	a[6].should.equal 3
+	a[7].should.equal 3.2
Index: frontend/node_modules/utila/test/object.coffee
===================================================================
--- frontend/node_modules/utila/test/object.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/utila/test/object.coffee	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,233 @@
+require './_prepare'
+
+object = mod 'object'
+
+test 'isBareObject', ->
+
+	object.isBareObject('a').should.equal false
+
+	object.isBareObject({'a': 'a'}).should.equal true
+
+test 'typeOf', ->
+
+	object.typeOf('s').should.equal 'string'
+	object.typeOf(0).should.equal 'number'
+	object.typeOf(false).should.equal 'boolean'
+	object.typeOf({}).should.equal 'object'
+	object.typeOf(arguments).should.equal 'arguments'
+	object.typeOf([]).should.equal 'array'
+
+test 'empty', ->
+
+	o =
+
+		a: 1
+		b: 2
+
+
+	object.empty o
+
+	o.should.not.have.property 'a'
+	o.should.not.have.property 'b'
+
+test 'fastEmpty', ->
+
+	o =
+		a: 1
+		b: 2
+
+
+	object.fastEmpty o
+
+	o.should.not.have.property 'a'
+	o.should.not.have.property 'b'
+
+test 'clone', ->
+
+	object.clone([1])[0].should.equal 1
+	object.clone({a:1}).a.should.equal 1
+
+	o = {a: 1}
+
+	object.clone(o).should.not.equal o
+
+test 'clone [include prototype]', ->
+
+	class C
+
+		constructor: (@a) ->
+
+		sayA: -> @a + 'a'
+
+	a = new C 'a'
+
+	a.sayA().should.equal 'aa'
+
+	b = object.clone a, yes
+
+	b.should.not.equal a
+
+	b.constructor.should.equal C
+
+	b.a.should.equal 'a'
+
+	b.a = 'a2'
+
+	b.sayA().should.equal 'a2a'
+
+test 'clone [without prototype]', ->
+
+	class C
+
+		constructor: (@a) ->
+
+		sayA: -> @a + 'a'
+
+	a = new C 'a'
+
+	a.sayA().should.equal 'aa'
+
+	b = object.clone a, no
+
+	b.should.equal a
+
+test 'overrideOnto [basic]', ->
+
+	onto =
+		a: 'a'
+		b:
+			c: 'c'
+			d:
+				e: 'e'
+
+	what =
+		a: 'a2'
+		b:
+			c: 'c2'
+			d:
+				f: 'f2'
+
+	object.overrideOnto onto, what
+
+	onto.a.should.equal 'a2'
+	onto.b.should.have.property 'c'
+	onto.b.c.should.equal 'c2'
+	onto.b.d.should.not.have.property 'f'
+	onto.b.d.e.should.equal 'e'
+
+test 'override', ->
+
+	onto =
+
+		a: 'a'
+
+		b:
+
+			c: 'c'
+
+			d:
+
+				e: 'e'
+
+	what =
+
+		a: 'a2'
+
+		b:
+
+			c: 'c2'
+
+			d:
+
+				f: 'f2'
+
+
+	onto2 = object.override onto, what
+
+	onto2.a.should.equal 'a2'
+	onto2.b.should.have.property 'c'
+	onto2.b.c.should.equal 'c2'
+	onto2.b.d.should.not.have.property 'f'
+	onto2.b.d.e.should.equal 'e'
+
+	onto.should.not.equal onto2
+
+do ->
+
+	what =
+
+		a: 'a2'
+
+		c: ->
+
+		z: 'z'
+
+		y:
+
+			a: 'a'
+
+	onto =
+
+		a: 'a'
+
+		b: 'b'
+
+	test 'appendOnto [basic]', ->
+
+		object.appendOnto onto, what
+
+		onto.a.should.equal 'a2'
+		onto.b.should.equal 'b'
+		onto.z.should.equal 'z'
+
+	test "appendOnto [shallow copies instances]", ->
+
+		onto.c.should.be.instanceof Function
+		onto.c.should.equal what.c
+
+
+	test "appendOnto [clones objects]", ->
+
+		onto.should.have.property 'y'
+		onto.y.a.should.equal 'a'
+		onto.y.should.not.equal what.y
+
+test 'groupProps', ->
+
+	obj =
+
+		a1: '1'
+		a2: '2'
+
+		b1: '1'
+		b2: '2'
+
+		c1: '1'
+		c2: '2'
+
+		rest1: '1'
+		rest2: '2'
+
+	groups = object.groupProps obj,
+
+		a: ['a1', 'a2']
+
+		b: [/^b[0-9]+$/]
+
+		c: (key) -> key[0] is 'c'
+
+	groups.a.should.have.property 'a1'
+	groups.a.a1.should.equal '1'
+
+	groups.a.should.have.property 'a2'
+
+	groups.b.should.have.property 'b1'
+	groups.b.should.have.property 'b2'
+
+	groups.c.should.have.property 'c1'
+	groups.c.should.have.property 'c2'
+
+	groups.rest.should.have.property 'rest1'
+	groups.rest.should.have.property 'rest1'
+
+	groups.rest.should.not.have.property 'c1'
