Index: frontend/node_modules/stable/README.md
===================================================================
--- frontend/node_modules/stable/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/stable/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,85 @@
+## Stable
+
+A stable array sort, because `Array#sort()` is not guaranteed stable.
+
+MIT licensed.
+
+[![Node.js CI](https://secure.travis-ci.org/Two-Screen/stable.png)](http://travis-ci.org/Two-Screen/stable)
+
+[![Browser CI](http://ci.testling.com/Two-Screen/stable.png)](http://ci.testling.com/Two-Screen/stable)
+
+#### From npm
+
+Install with:
+
+```sh
+npm install stable
+```
+
+Then use it in Node.js or some other CommonJS environment as:
+
+```js
+const stable = require('stable')
+```
+
+#### From the browser
+
+Include [`stable.js`] or the minified version [`stable.min.js`]
+in your page, then call `stable()`.
+
+ [`stable.js`]: https://raw.github.com/Two-Screen/stable/master/stable.js
+ [`stable.min.js`]: https://raw.github.com/Two-Screen/stable/master/stable.min.js
+
+#### Usage
+
+The default sort is, as with `Array#sort`, lexicographical:
+
+```js
+stable(['foo', 'bar', 'baz'])  // => ['bar', 'baz', 'foo']
+stable([10, 1, 5])             // => [1, 10, 5]
+```
+
+Unlike `Array#sort`, the default sort is **NOT** in-place. To do an in-place
+sort, use `stable.inplace`, which otherwise works the same:
+
+```js
+const arr = [10, 1, 5]
+stable(arr) === arr          // => false
+stable.inplace(arr) === arr  // => true
+```
+
+A comparator function can be specified:
+
+```js
+// Regular sort() compatible comparator, that returns a number.
+// This demonstrates the default behavior.
+const lexCmp = (a, b) => String(a).localeCompare(b)
+stable(['foo', 'bar', 'baz'], lexCmp)  // => ['bar', 'baz', 'foo']
+
+// Boolean comparator. Sorts `b` before `a` if true.
+// This demonstrates a simple way to sort numerically.
+const greaterThan = (a, b) => a > b
+stable([10, 1, 5], greaterThan)  // => [1, 5, 10]
+```
+
+#### License
+
+Copyright (C) 2018 Angry Bytes and contributors.
+
+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/stable/index.d.ts
===================================================================
--- frontend/node_modules/stable/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/stable/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,9 @@
+export as namespace stable;
+export = stable;
+
+type Comparator<T> = ((a : T, b : T)=>boolean) | ((a: T, b : T)=>number);
+
+declare function stable<T>(array : T[], comparator? : Comparator<T>) : T[];
+declare namespace stable {
+    export function inplace<T>(array: T[], comparator? : Comparator<T>) : T[];
+}
Index: frontend/node_modules/stable/package.json
===================================================================
--- frontend/node_modules/stable/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/stable/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,58 @@
+{
+    "name": "stable",
+    "version": "0.1.8",
+    "keywords": [
+        "stable",
+        "array",
+        "sort"
+    ],
+    "description": "A stable array sort for JavaScript",
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/Two-Screen/stable.git"
+    },
+    "main": "./stable.js",
+    "types": "./index.d.ts",
+    "files": [
+        "stable.js",
+        "stable.min.js",
+        "index.d.ts"
+    ],
+    "devDependencies": {
+        "rollup": "^0.57.1",
+        "standard": "^11.0.1",
+        "tape": "^4.6.3",
+        "uglify-js": "^3.3.21"
+    },
+    "scripts": {
+        "test": "standard src/ && node ./src/test.js",
+        "prepare": "npm run build && npm run minify",
+        "build": "rollup -c",
+        "minify": "uglifyjs --comments \"/^!/\" -c -m -o ./stable.min.js ./stable.js"
+    },
+    "testling": {
+        "files": "./src/test.js",
+        "browsers": [
+            "ie6",
+            "ie7",
+            "ie8",
+            "ie9",
+            "ie10",
+            "firefox/25",
+            "chrome/31",
+            "safari/6.0",
+            "opera/12.0",
+            "opera/17.0",
+            "iphone/6.0",
+            "android-browser/4.2"
+        ]
+    },
+    "author": "Angry Bytes <info@angrybytes.com>",
+    "contributors": [
+        "Domenic Denicola <domenic@domenicdenicola.com>",
+        "Mattias Buelens <mattias@buelens.com>",
+        "Stéphan Kochen <stephan@angrybytes.com>",
+        "Yaffle"
+    ],
+    "license": "MIT"
+}
Index: frontend/node_modules/stable/stable.js
===================================================================
--- frontend/node_modules/stable/stable.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/stable/stable.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,109 @@
+//! stable.js 0.1.8, https://github.com/Two-Screen/stable
+//! © 2018 Angry Bytes and contributors. MIT licensed.
+
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global.stable = factory());
+}(this, (function () { 'use strict';
+
+  // A stable array sort, because `Array#sort()` is not guaranteed stable.
+  // This is an implementation of merge sort, without recursion.
+
+  var stable = function (arr, comp) {
+    return exec(arr.slice(), comp)
+  };
+
+  stable.inplace = function (arr, comp) {
+    var result = exec(arr, comp);
+
+    // This simply copies back if the result isn't in the original array,
+    // which happens on an odd number of passes.
+    if (result !== arr) {
+      pass(result, null, arr.length, arr);
+    }
+
+    return arr
+  };
+
+  // Execute the sort using the input array and a second buffer as work space.
+  // Returns one of those two, containing the final result.
+  function exec(arr, comp) {
+    if (typeof(comp) !== 'function') {
+      comp = function (a, b) {
+        return String(a).localeCompare(b)
+      };
+    }
+
+    // Short-circuit when there's nothing to sort.
+    var len = arr.length;
+    if (len <= 1) {
+      return arr
+    }
+
+    // Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc.
+    // Chunks are the size of the left or right hand in merge sort.
+    // Stop when the left-hand covers all of the array.
+    var buffer = new Array(len);
+    for (var chk = 1; chk < len; chk *= 2) {
+      pass(arr, comp, chk, buffer);
+
+      var tmp = arr;
+      arr = buffer;
+      buffer = tmp;
+    }
+
+    return arr
+  }
+
+  // Run a single pass with the given chunk size.
+  var pass = function (arr, comp, chk, result) {
+    var len = arr.length;
+    var i = 0;
+    // Step size / double chunk size.
+    var dbl = chk * 2;
+    // Bounds of the left and right chunks.
+    var l, r, e;
+    // Iterators over the left and right chunk.
+    var li, ri;
+
+    // Iterate over pairs of chunks.
+    for (l = 0; l < len; l += dbl) {
+      r = l + chk;
+      e = r + chk;
+      if (r > len) r = len;
+      if (e > len) e = len;
+
+      // Iterate both chunks in parallel.
+      li = l;
+      ri = r;
+      while (true) {
+        // Compare the chunks.
+        if (li < r && ri < e) {
+          // This works for a regular `sort()` compatible comparator,
+          // but also for a simple comparator like: `a > b`
+          if (comp(arr[li], arr[ri]) <= 0) {
+            result[i++] = arr[li++];
+          }
+          else {
+            result[i++] = arr[ri++];
+          }
+        }
+        // Nothing to compare, just flush what's left.
+        else if (li < r) {
+          result[i++] = arr[li++];
+        }
+        else if (ri < e) {
+          result[i++] = arr[ri++];
+        }
+        // Both iterators are at the chunk ends.
+        else {
+          break
+        }
+      }
+    }
+  };
+
+  return stable;
+
+})));
Index: frontend/node_modules/stable/stable.min.js
===================================================================
--- frontend/node_modules/stable/stable.min.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/stable/stable.min.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,3 @@
+//! stable.js 0.1.8, https://github.com/Two-Screen/stable
+//! © 2018 Angry Bytes and contributors. MIT licensed.
+!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.stable=n()}(this,function(){"use strict";var e=function(e,n){return t(e.slice(),n)};function t(e,n){"function"!=typeof n&&(n=function(e,n){return String(e).localeCompare(n)});var r=e.length;if(r<=1)return e;for(var t=new Array(r),f=1;f<r;f*=2){i(e,n,f,t);var o=e;e=t,t=o}return e}e.inplace=function(e,n){var r=t(e,n);return r!==e&&i(r,null,e.length,e),e};var i=function(e,n,r,t){var f,o,i,u,a,c=e.length,l=0,s=2*r;for(f=0;f<c;f+=s)for(i=(o=f+r)+r,c<o&&(o=c),c<i&&(i=c),u=f,a=o;;)if(u<o&&a<i)n(e[u],e[a])<=0?t[l++]=e[u++]:t[l++]=e[a++];else if(u<o)t[l++]=e[u++];else{if(!(a<i))break;t[l++]=e[a++]}};return e});
