Index: frontend/node_modules/jsesc/LICENSE-MIT.txt
===================================================================
--- frontend/node_modules/jsesc/LICENSE-MIT.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/LICENSE-MIT.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+Copyright Mathias Bynens <https://mathiasbynens.be/>
+
+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/jsesc/README.md
===================================================================
--- frontend/node_modules/jsesc/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,422 @@
+# jsesc
+
+Given some data, _jsesc_ returns a stringified representation of that data. jsesc is similar to `JSON.stringify()` except:
+
+1. it outputs JavaScript instead of JSON [by default](#json), enabling support for data structures like ES6 maps and sets;
+2. it offers [many options](#api) to customize the output;
+3. its output is ASCII-safe [by default](#minimal), thanks to its use of [escape sequences](https://mathiasbynens.be/notes/javascript-escapes) where needed.
+
+For any input, jsesc generates the shortest possible valid printable-ASCII-only output. [Here’s an online demo.](https://mothereff.in/js-escapes)
+
+jsesc’s output can be used instead of `JSON.stringify`’s to avoid [mojibake](https://en.wikipedia.org/wiki/Mojibake) and other encoding issues, or even to [avoid errors](https://twitter.com/annevk/status/380000829643571200) when passing JSON-formatted data (which may contain U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR, or [lone surrogates](https://esdiscuss.org/topic/code-points-vs-unicode-scalar-values#content-14)) to a JavaScript parser or an UTF-8 encoder.
+
+## Installation
+
+Via [npm](https://www.npmjs.com/):
+
+```bash
+npm install jsesc
+```
+
+In [Node.js](https://nodejs.org/):
+
+```js
+const jsesc = require('jsesc');
+```
+
+## API
+
+### `jsesc(value, options)`
+
+This function takes a value and returns an escaped version of the value where any characters that are not printable ASCII symbols are escaped using the shortest possible (but valid) [escape sequences for use in JavaScript strings](https://mathiasbynens.be/notes/javascript-escapes). The first supported value type is strings:
+
+```js
+jsesc('Ich ♥ Bücher');
+// → 'Ich \\u2665 B\\xFCcher'
+
+jsesc('foo 𝌆 bar');
+// → 'foo \\uD834\\uDF06 bar'
+```
+
+Instead of a string, the `value` can also be an array, an object, a map, a set, or a buffer. In such cases, `jsesc` returns a stringified version of the value where any characters that are not printable ASCII symbols are escaped in the same way.
+
+```js
+// Escaping an array
+jsesc([
+  'Ich ♥ Bücher', 'foo 𝌆 bar'
+]);
+// → '[\'Ich \\u2665 B\\xFCcher\',\'foo \\uD834\\uDF06 bar\']'
+
+// Escaping an object
+jsesc({
+  'Ich ♥ Bücher': 'foo 𝌆 bar'
+});
+// → '{\'Ich \\u2665 B\\xFCcher\':\'foo \\uD834\\uDF06 bar\'}'
+```
+
+The optional `options` argument accepts an object with the following options:
+
+#### `quotes`
+
+The default value for the `quotes` option is `'single'`. This means that any occurrences of `'` in the input string are escaped as `\'`, so that the output can be used in a string literal wrapped in single quotes.
+
+```js
+jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.');
+// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
+
+jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
+  'quotes': 'single'
+});
+// → '`Lorem` ipsum "dolor" sit \\\'amet\\\' etc.'
+// → "`Lorem` ipsum \"dolor\" sit \\'amet\\' etc."
+```
+
+If you want to use the output as part of a string literal wrapped in double quotes, set the `quotes` option to `'double'`.
+
+```js
+jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
+  'quotes': 'double'
+});
+// → '`Lorem` ipsum \\"dolor\\" sit \'amet\' etc.'
+// → "`Lorem` ipsum \\\"dolor\\\" sit 'amet' etc."
+```
+
+If you want to use the output as part of a template literal (i.e. wrapped in backticks), set the `quotes` option to `'backtick'`.
+
+```js
+jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
+  'quotes': 'backtick'
+});
+// → '\\`Lorem\\` ipsum "dolor" sit \'amet\' etc.'
+// → "\\`Lorem\\` ipsum \"dolor\" sit 'amet' etc."
+// → `\\\`Lorem\\\` ipsum "dolor" sit 'amet' etc.`
+```
+
+This setting also affects the output for arrays and objects:
+
+```js
+jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
+  'quotes': 'double'
+});
+// → '{"Ich \\u2665 B\\xFCcher":"foo \\uD834\\uDF06 bar"}'
+
+jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
+  'quotes': 'double'
+});
+// → '["Ich \\u2665 B\\xFCcher","foo \\uD834\\uDF06 bar"]'
+```
+
+#### `numbers`
+
+The default value for the `numbers` option is `'decimal'`. This means that any numeric values are represented using decimal integer literals. Other valid options are `binary`, `octal`, and `hexadecimal`, which result in binary integer literals, octal integer literals, and hexadecimal integer literals, respectively.
+
+```js
+jsesc(42, {
+  'numbers': 'binary'
+});
+// → '0b101010'
+
+jsesc(42, {
+  'numbers': 'octal'
+});
+// → '0o52'
+
+jsesc(42, {
+  'numbers': 'decimal'
+});
+// → '42'
+
+jsesc(42, {
+  'numbers': 'hexadecimal'
+});
+// → '0x2A'
+```
+
+#### `wrap`
+
+The `wrap` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output is a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified through the `quotes` setting.
+
+```js
+jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
+  'quotes': 'single',
+  'wrap': true
+});
+// → '\'Lorem ipsum "dolor" sit \\\'amet\\\' etc.\''
+// → "\'Lorem ipsum \"dolor\" sit \\\'amet\\\' etc.\'"
+
+jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
+  'quotes': 'double',
+  'wrap': true
+});
+// → '"Lorem ipsum \\"dolor\\" sit \'amet\' etc."'
+// → "\"Lorem ipsum \\\"dolor\\\" sit \'amet\' etc.\""
+```
+
+#### `es6`
+
+The `es6` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, any astral Unicode symbols in the input are escaped using [ECMAScript 6 Unicode code point escape sequences](https://mathiasbynens.be/notes/javascript-escapes#unicode-code-point) instead of using separate escape sequences for each surrogate half. If backwards compatibility with ES5 environments is a concern, don’t enable this setting. If the `json` setting is enabled, the value for the `es6` setting is ignored (as if it was `false`).
+
+```js
+// By default, the `es6` option is disabled:
+jsesc('foo 𝌆 bar 💩 baz');
+// → 'foo \\uD834\\uDF06 bar \\uD83D\\uDCA9 baz'
+
+// To explicitly disable it:
+jsesc('foo 𝌆 bar 💩 baz', {
+  'es6': false
+});
+// → 'foo \\uD834\\uDF06 bar \\uD83D\\uDCA9 baz'
+
+// To enable it:
+jsesc('foo 𝌆 bar 💩 baz', {
+  'es6': true
+});
+// → 'foo \\u{1D306} bar \\u{1F4A9} baz'
+```
+
+#### `escapeEverything`
+
+The `escapeEverything` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, all the symbols in the output are escaped — even printable ASCII symbols.
+
+```js
+jsesc('lolwat"foo\'bar', {
+  'escapeEverything': true
+});
+// → '\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72'
+// → "\\x6C\\x6F\\x6C\\x77\\x61\\x74\\\"\\x66\\x6F\\x6F\\'\\x62\\x61\\x72"
+```
+
+This setting also affects the output for string literals within arrays and objects.
+
+#### `minimal`
+
+The `minimal` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, only a limited set of symbols in the output are escaped:
+
+* U+0000 `\0`
+* U+0008 `\b`
+* U+0009 `\t`
+* U+000A `\n`
+* U+000C `\f`
+* U+000D `\r`
+* U+005C `\\`
+* U+2028 `\u2028`
+* U+2029 `\u2029`
+* whatever symbol is being used for wrapping string literals (based on [the `quotes` option](#quotes))
+* [lone surrogates](https://esdiscuss.org/topic/code-points-vs-unicode-scalar-values#content-14)
+
+Note: with this option enabled, jsesc output is no longer guaranteed to be ASCII-safe.
+
+```js
+jsesc('foo\u2029bar\nbaz©qux𝌆flops', {
+  'minimal': false
+});
+// → 'foo\\u2029bar\\nbaz©qux𝌆flops'
+```
+
+#### `isScriptContext`
+
+The `isScriptContext` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, occurrences of [`</script` and `</style`](https://mathiasbynens.be/notes/etago) in the output are escaped as `<\/script` and `<\/style`, and [`<!--`](https://mathiasbynens.be/notes/etago#comment-8) is escaped as `\x3C!--` (or `\u003C!--` when the `json` option is enabled). This setting is useful when jsesc’s output ends up as part of a `<script>` or `<style>` element in an HTML document.
+
+```js
+jsesc('foo</script>bar', {
+  'isScriptContext': true
+});
+// → 'foo<\\/script>bar'
+```
+
+#### `compact`
+
+The `compact` option takes a boolean value (`true` or `false`), and defaults to `true` (enabled). When enabled, the output for arrays and objects is as compact as possible; it’s not formatted nicely.
+
+```js
+jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
+  'compact': true // this is the default
+});
+// → '{\'Ich \u2665 B\xFCcher\':\'foo \uD834\uDF06 bar\'}'
+
+jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
+  'compact': false
+});
+// → '{\n\t\'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
+
+jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
+  'compact': false
+});
+// → '[\n\t\'Ich \u2665 B\xFCcher\',\n\t\'foo \uD834\uDF06 bar\'\n]'
+```
+
+This setting has no effect on the output for strings.
+
+#### `indent`
+
+The `indent` option takes a string value, and defaults to `'\t'`. When the `compact` setting is disabled (`false`), the value of the `indent` option is used to format the output for arrays and objects.
+
+```js
+jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
+  'compact': false,
+  'indent': '\t' // this is the default
+});
+// → '{\n\t\'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
+
+jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
+  'compact': false,
+  'indent': '  '
+});
+// → '{\n  \'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
+
+jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
+  'compact': false,
+  'indent': '  '
+});
+// → '[\n  \'Ich \u2665 B\xFCcher\',\n\  t\'foo \uD834\uDF06 bar\'\n]'
+```
+
+This setting has no effect on the output for strings.
+
+#### `indentLevel`
+
+The `indentLevel` option takes a numeric value, and defaults to `0`. It represents the current indentation level, i.e. the number of times the value of [the `indent` option](#indent) is repeated.
+
+```js
+jsesc(['a', 'b', 'c'], {
+  'compact': false,
+  'indentLevel': 1
+});
+// → '[\n\t\t\'a\',\n\t\t\'b\',\n\t\t\'c\'\n\t]'
+
+jsesc(['a', 'b', 'c'], {
+  'compact': false,
+  'indentLevel': 2
+});
+// → '[\n\t\t\t\'a\',\n\t\t\t\'b\',\n\t\t\t\'c\'\n\t\t]'
+```
+
+#### `json`
+
+The `json` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output is valid JSON. [Hexadecimal character escape sequences](https://mathiasbynens.be/notes/javascript-escapes#hexadecimal) and [the `\v` or `\0` escape sequences](https://mathiasbynens.be/notes/javascript-escapes#single) are not used. Setting `json: true` implies `quotes: 'double', wrap: true, es6: false`, although these values can still be overridden if needed — but in such cases, the output won’t be valid JSON anymore.
+
+```js
+jsesc('foo\x00bar\xFF\uFFFDbaz', {
+  'json': true
+});
+// → '"foo\\u0000bar\\u00FF\\uFFFDbaz"'
+
+jsesc({ 'foo\x00bar\xFF\uFFFDbaz': 'foo\x00bar\xFF\uFFFDbaz' }, {
+  'json': true
+});
+// → '{"foo\\u0000bar\\u00FF\\uFFFDbaz":"foo\\u0000bar\\u00FF\\uFFFDbaz"}'
+
+jsesc([ 'foo\x00bar\xFF\uFFFDbaz', 'foo\x00bar\xFF\uFFFDbaz' ], {
+  'json': true
+});
+// → '["foo\\u0000bar\\u00FF\\uFFFDbaz","foo\\u0000bar\\u00FF\\uFFFDbaz"]'
+
+// Values that are acceptable in JSON but aren’t strings, arrays, or object
+// literals can’t be escaped, so they’ll just be preserved:
+jsesc([ 'foo\x00bar', [1, '©', { 'foo': true, 'qux': null }], 42 ], {
+  'json': true
+});
+// → '["foo\\u0000bar",[1,"\\u00A9",{"foo":true,"qux":null}],42]'
+// Values that aren’t allowed in JSON are run through `JSON.stringify()`:
+jsesc([ undefined, -Infinity ], {
+  'json': true
+});
+// → '[null,null]'
+```
+
+**Note:** Using this option on objects or arrays that contain non-string values relies on `JSON.stringify()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](http://bestiejs.github.io/json3/).
+
+#### `lowercaseHex`
+
+The `lowercaseHex` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, any alphabetical hexadecimal digits in escape sequences as well as any hexadecimal integer literals (see [the `numbers` option](#numbers)) in the output are in lowercase.
+
+```js
+jsesc('Ich ♥ Bücher', {
+  'lowercaseHex': true
+});
+// → 'Ich \\u2665 B\\xfccher'
+//                    ^^
+
+jsesc(42, {
+  'numbers': 'hexadecimal',
+  'lowercaseHex': true
+});
+// → '0x2a'
+//      ^^
+```
+
+### `jsesc.version`
+
+A string representing the semantic version number.
+
+### Using the `jsesc` binary
+
+To use the `jsesc` binary in your shell, simply install jsesc globally using npm:
+
+```bash
+npm install -g jsesc
+```
+
+After that you’re able to escape strings from the command line:
+
+```bash
+$ jsesc 'föo ♥ bår 𝌆 baz'
+f\xF6o \u2665 b\xE5r \uD834\uDF06 baz
+```
+
+To escape arrays or objects containing string values, use the `-o`/`--object` option:
+
+```bash
+$ jsesc --object '{ "föo": "♥", "bår": "𝌆 baz" }'
+{'f\xF6o':'\u2665','b\xE5r':'\uD834\uDF06 baz'}
+```
+
+To prettify the output in such cases, use the `-p`/`--pretty` option:
+
+```bash
+$ jsesc --pretty '{ "föo": "♥", "bår": "𝌆 baz" }'
+{
+  'f\xF6o': '\u2665',
+  'b\xE5r': '\uD834\uDF06 baz'
+}
+```
+
+For valid JSON output, use the `-j`/`--json` option:
+
+```bash
+$ jsesc --json --pretty '{ "föo": "♥", "bår": "𝌆 baz" }'
+{
+  "f\u00F6o": "\u2665",
+  "b\u00E5r": "\uD834\uDF06 baz"
+}
+```
+
+Read a local JSON file, escape any non-ASCII symbols, and save the result to a new file:
+
+```bash
+$ jsesc --json --object < data-raw.json > data-escaped.json
+```
+
+Or do the same with an online JSON file:
+
+```bash
+$ curl -sL "http://git.io/aorKgQ" | jsesc --json --object > data-escaped.json
+```
+
+See `jsesc --help` for the full list of options.
+
+## Support
+
+As of v3.0.0, jsesc supports Node.js v6+ only.
+
+Older versions (up to jsesc v1.3.0) support Chrome 27, Firefox 3, Safari 4, Opera 10, IE 6, Node.js v6.0.0, Narwhal 0.3.2, RingoJS 0.8-0.11, PhantomJS 1.9.0, and Rhino 1.7RC4. **Note:** Using the `json` option on objects or arrays that contain non-string values relies on `JSON.parse()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](https://bestiejs.github.io/json3/).
+
+## Author
+
+| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
+|---|
+| [Mathias Bynens](https://mathiasbynens.be/) |
+
+## License
+
+This library is available under the [MIT](https://mths.be/mit) license.
Index: frontend/node_modules/jsesc/bin/jsesc
===================================================================
--- frontend/node_modules/jsesc/bin/jsesc	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/bin/jsesc	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,148 @@
+#!/usr/bin/env node
+(function() {
+
+	var fs = require('fs');
+	var stringEscape = require('../jsesc.js');
+	var strings = process.argv.splice(2);
+	var stdin = process.stdin;
+	var data;
+	var timeout;
+	var isObject = false;
+	var options = {};
+	var log = console.log;
+
+	var main = function() {
+		var option = strings[0];
+
+		if (/^(?:-h|--help|undefined)$/.test(option)) {
+			log(
+				'jsesc v%s - https://mths.be/jsesc',
+				stringEscape.version
+			);
+			log([
+				'\nUsage:\n',
+				'\tjsesc [string]',
+				'\tjsesc [-s | --single-quotes] [string]',
+				'\tjsesc [-d | --double-quotes] [string]',
+				'\tjsesc [-w | --wrap] [string]',
+				'\tjsesc [-e | --escape-everything] [string]',
+				'\tjsesc [-t | --escape-etago] [string]',
+				'\tjsesc [-6 | --es6] [string]',
+				'\tjsesc [-l | --lowercase-hex] [string]',
+				'\tjsesc [-j | --json] [string]',
+				'\tjsesc [-o | --object] [stringified_object]', // `JSON.parse()` the argument
+				'\tjsesc [-p | --pretty] [string]', // `compact: false`
+				'\tjsesc [-v | --version]',
+				'\tjsesc [-h | --help]',
+				'\nExamples:\n',
+				'\tjsesc \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
+				'\tjsesc --json \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
+				'\tjsesc --json --escape-everything \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
+				'\tjsesc --double-quotes --wrap \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
+				'\techo \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\' | jsesc'
+			].join('\n'));
+			return process.exit(1);
+		}
+
+		if (/^(?:-v|--version)$/.test(option)) {
+			log('v%s', stringEscape.version);
+			return process.exit(1);
+		}
+
+		strings.forEach(function(string) {
+			// Process options
+			if (/^(?:-s|--single-quotes)$/.test(string)) {
+				options.quotes = 'single';
+				return;
+			}
+			if (/^(?:-d|--double-quotes)$/.test(string)) {
+				options.quotes = 'double';
+				return;
+			}
+			if (/^(?:-w|--wrap)$/.test(string)) {
+				options.wrap = true;
+				return;
+			}
+			if (/^(?:-e|--escape-everything)$/.test(string)) {
+				options.escapeEverything = true;
+				return;
+			}
+			if (/^(?:-t|--escape-etago)$/.test(string)) {
+				options.escapeEtago = true;
+				return;
+			}
+			if (/^(?:-6|--es6)$/.test(string)) {
+				options.es6 = true;
+				return;
+			}
+			if (/^(?:-l|--lowercase-hex)$/.test(string)) {
+				options.lowercaseHex = true;
+				return;
+			}
+			if (/^(?:-j|--json)$/.test(string)) {
+				options.json = true;
+				return;
+			}
+			if (/^(?:-o|--object)$/.test(string)) {
+				isObject = true;
+				return;
+			}
+			if (/^(?:-p|--pretty)$/.test(string)) {
+				isObject = true;
+				options.compact = false;
+				return;
+			}
+
+			// Process string(s)
+			var result;
+			try {
+				if (isObject) {
+					string = JSON.parse(string);
+				}
+				result = stringEscape(string, options);
+				log(result);
+			} catch(error) {
+				log(error.message + '\n');
+				log('Error: failed to escape.');
+				log('If you think this is a bug in jsesc, please report it:');
+				log('https://github.com/mathiasbynens/jsesc/issues/new');
+				log(
+					'\nStack trace using jsesc@%s:\n',
+					stringEscape.version
+				);
+				log(error.stack);
+				return process.exit(1);
+			}
+		});
+		// Return with exit status 0 outside of the `forEach` loop, in case
+		// multiple strings were passed in.
+		return process.exit(0);
+
+	};
+
+	if (stdin.isTTY) {
+		// handle shell arguments
+		main();
+	} else {
+		// Either the script is called from within a non-TTY context,
+		// or `stdin` content is being piped in.
+		if (!process.stdout.isTTY) { // called from a non-TTY context
+			timeout = setTimeout(function() {
+				// if no piped data arrived after a while, handle shell arguments
+				main();
+			}, 250);
+		}
+
+		data = '';
+		stdin.on('data', function(chunk) {
+			clearTimeout(timeout);
+			data += chunk;
+		});
+		stdin.on('end', function() {
+			strings.push(data.trim());
+			main();
+		});
+		stdin.resume();
+	}
+
+}());
Index: frontend/node_modules/jsesc/jsesc.js
===================================================================
--- frontend/node_modules/jsesc/jsesc.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/jsesc.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,337 @@
+'use strict';
+
+const object = {};
+const hasOwnProperty = object.hasOwnProperty;
+const forOwn = (object, callback) => {
+	for (const key in object) {
+		if (hasOwnProperty.call(object, key)) {
+			callback(key, object[key]);
+		}
+	}
+};
+
+const extend = (destination, source) => {
+	if (!source) {
+		return destination;
+	}
+	forOwn(source, (key, value) => {
+		destination[key] = value;
+	});
+	return destination;
+};
+
+const forEach = (array, callback) => {
+	const length = array.length;
+	let index = -1;
+	while (++index < length) {
+		callback(array[index]);
+	}
+};
+
+const fourHexEscape = (hex) => {
+	return '\\u' + ('0000' + hex).slice(-4);
+}
+
+const hexadecimal = (code, lowercase) => {
+	let hexadecimal = code.toString(16);
+	if (lowercase) return hexadecimal;
+	return hexadecimal.toUpperCase();
+};
+
+const toString = object.toString;
+const isArray = Array.isArray;
+const isBuffer = (value) => {
+	return typeof Buffer === 'function' && Buffer.isBuffer(value);
+};
+const isObject = (value) => {
+	// This is a very simple check, but it’s good enough for what we need.
+	return toString.call(value) == '[object Object]';
+};
+const isString = (value) => {
+	return typeof value == 'string' ||
+		toString.call(value) == '[object String]';
+};
+const isNumber = (value) => {
+	return typeof value == 'number' ||
+		toString.call(value) == '[object Number]';
+};
+const isBigInt = (value) => {
+  return typeof value == 'bigint';
+};
+const isFunction = (value) => {
+	return typeof value == 'function';
+};
+const isMap = (value) => {
+	return toString.call(value) == '[object Map]';
+};
+const isSet = (value) => {
+	return toString.call(value) == '[object Set]';
+};
+
+/*--------------------------------------------------------------------------*/
+
+// https://mathiasbynens.be/notes/javascript-escapes#single
+const singleEscapes = {
+	'\\': '\\\\',
+	'\b': '\\b',
+	'\f': '\\f',
+	'\n': '\\n',
+	'\r': '\\r',
+	'\t': '\\t'
+	// `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
+	// '\v': '\\x0B'
+};
+const regexSingleEscape = /[\\\b\f\n\r\t]/;
+
+const regexDigit = /[0-9]/;
+const regexWhitespace = /[\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;
+
+const escapeEverythingRegex = /([\uD800-\uDBFF][\uDC00-\uDFFF])|([\uD800-\uDFFF])|(['"`])|[^]/g;
+const escapeNonAsciiRegex = /([\uD800-\uDBFF][\uDC00-\uDFFF])|([\uD800-\uDFFF])|(['"`])|[^ !#-&\(-\[\]-_a-~]/g;
+
+const jsesc = (argument, options) => {
+	const increaseIndentation = () => {
+		oldIndent = indent;
+		++options.indentLevel;
+		indent = options.indent.repeat(options.indentLevel)
+	};
+	// Handle options
+	const defaults = {
+		'escapeEverything': false,
+		'minimal': false,
+		'isScriptContext': false,
+		'quotes': 'single',
+		'wrap': false,
+		'es6': false,
+		'json': false,
+		'compact': true,
+		'lowercaseHex': false,
+		'numbers': 'decimal',
+		'indent': '\t',
+		'indentLevel': 0,
+		'__inline1__': false,
+		'__inline2__': false
+	};
+	const json = options && options.json;
+	if (json) {
+		defaults.quotes = 'double';
+		defaults.wrap = true;
+	}
+	options = extend(defaults, options);
+	if (
+		options.quotes != 'single' &&
+		options.quotes != 'double' &&
+		options.quotes != 'backtick'
+	) {
+		options.quotes = 'single';
+	}
+	const quote = options.quotes == 'double' ?
+		'"' :
+		(options.quotes == 'backtick' ?
+			'`' :
+			'\''
+		);
+	const compact = options.compact;
+	const lowercaseHex = options.lowercaseHex;
+	let indent = options.indent.repeat(options.indentLevel);
+	let oldIndent = '';
+	const inline1 = options.__inline1__;
+	const inline2 = options.__inline2__;
+	const newLine = compact ? '' : '\n';
+	let result;
+	let isEmpty = true;
+	const useBinNumbers = options.numbers == 'binary';
+	const useOctNumbers = options.numbers == 'octal';
+	const useDecNumbers = options.numbers == 'decimal';
+	const useHexNumbers = options.numbers == 'hexadecimal';
+
+	if (json && argument && isFunction(argument.toJSON)) {
+		argument = argument.toJSON();
+	}
+
+	if (!isString(argument)) {
+		if (isMap(argument)) {
+			if (argument.size == 0) {
+				return 'new Map()';
+			}
+			if (!compact) {
+				options.__inline1__ = true;
+				options.__inline2__ = false;
+			}
+			return 'new Map(' + jsesc(Array.from(argument), options) + ')';
+		}
+		if (isSet(argument)) {
+			if (argument.size == 0) {
+				return 'new Set()';
+			}
+			return 'new Set(' + jsesc(Array.from(argument), options) + ')';
+		}
+		if (isBuffer(argument)) {
+			if (argument.length == 0) {
+				return 'Buffer.from([])';
+			}
+			return 'Buffer.from(' + jsesc(Array.from(argument), options) + ')';
+		}
+		if (isArray(argument)) {
+			result = [];
+			options.wrap = true;
+			if (inline1) {
+				options.__inline1__ = false;
+				options.__inline2__ = true;
+			}
+			if (!inline2) {
+				increaseIndentation();
+			}
+			forEach(argument, (value) => {
+				isEmpty = false;
+				if (inline2) {
+					options.__inline2__ = false;
+				}
+				result.push(
+					(compact || inline2 ? '' : indent) +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '[]';
+			}
+			if (inline2) {
+				return '[' + result.join(', ') + ']';
+			}
+			return '[' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + ']';
+		} else if (isNumber(argument) || isBigInt(argument)) {
+			if (json) {
+				// Some number values (e.g. `Infinity`) cannot be represented in JSON.
+				// `BigInt` values less than `-Number.MAX_VALUE` or greater than
+        // `Number.MAX_VALUE` cannot be represented in JSON so they will become
+        // `-Infinity` or `Infinity`, respectively, and then become `null` when
+        // stringified.
+				return JSON.stringify(Number(argument));
+			}
+
+      let result;
+			if (useDecNumbers) {
+				result = String(argument);
+			} else if (useHexNumbers) {
+				let hexadecimal = argument.toString(16);
+				if (!lowercaseHex) {
+					hexadecimal = hexadecimal.toUpperCase();
+				}
+				result = '0x' + hexadecimal;
+			} else if (useBinNumbers) {
+				result = '0b' + argument.toString(2);
+			} else if (useOctNumbers) {
+				result = '0o' + argument.toString(8);
+			}
+
+      if (isBigInt(argument)) {
+        return result + 'n';
+      }
+      return result;
+		} else if (isBigInt(argument)) {
+			if (json) {
+				// `BigInt` values less than `-Number.MAX_VALUE` or greater than
+        // `Number.MAX_VALUE` will become `-Infinity` or `Infinity`,
+        // respectively, and cannot be represented in JSON.
+				return JSON.stringify(Number(argument));
+			}
+      return argument + 'n';
+    } else if (!isObject(argument)) {
+			if (json) {
+				// For some values (e.g. `undefined`, `function` objects),
+				// `JSON.stringify(value)` returns `undefined` (which isn’t valid
+				// JSON) instead of `'null'`.
+				return JSON.stringify(argument) || 'null';
+			}
+			return String(argument);
+		} else { // it’s an object
+			result = [];
+			options.wrap = true;
+			increaseIndentation();
+			forOwn(argument, (key, value) => {
+				isEmpty = false;
+				result.push(
+					(compact ? '' : indent) +
+					jsesc(key, options) + ':' +
+					(compact ? '' : ' ') +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '{}';
+			}
+			return '{' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + '}';
+		}
+	}
+
+	const regex = options.escapeEverything ? escapeEverythingRegex : escapeNonAsciiRegex;
+	result = argument.replace(regex, (char, pair, lone, quoteChar, index, string) => {
+		if (pair) {
+			if (options.minimal) return pair;
+			const first = pair.charCodeAt(0);
+			const second = pair.charCodeAt(1);
+			if (options.es6) {
+				// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+				const codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+				const hex = hexadecimal(codePoint, lowercaseHex);
+				return '\\u{' + hex + '}';
+			}
+			return fourHexEscape(hexadecimal(first, lowercaseHex)) + fourHexEscape(hexadecimal(second, lowercaseHex));
+		}
+
+		if (lone) {
+			return fourHexEscape(hexadecimal(lone.charCodeAt(0), lowercaseHex));
+		}
+
+		if (
+			char == '\0' &&
+			!json &&
+			!regexDigit.test(string.charAt(index + 1))
+		) {
+			return '\\0';
+		}
+
+		if (quoteChar) {
+			if (quoteChar == quote || options.escapeEverything) {
+				return '\\' + quoteChar;
+			}
+			return quoteChar;
+		}
+
+		if (regexSingleEscape.test(char)) {
+			// no need for a `hasOwnProperty` check here
+			return singleEscapes[char];
+		}
+
+		if (options.minimal && !regexWhitespace.test(char)) {
+			return char;
+		}
+
+		const hex = hexadecimal(char.charCodeAt(0), lowercaseHex);
+		if (json || hex.length > 2) {
+			return fourHexEscape(hex);
+		}
+
+		return '\\x' + ('00' + hex).slice(-2);
+	});
+
+	if (quote == '`') {
+		result = result.replace(/\$\{/g, '\\${');
+	}
+	if (options.isScriptContext) {
+		// https://mathiasbynens.be/notes/etago
+		result = result
+			.replace(/<\/(script|style)/gi, '<\\/$1')
+			.replace(/<!--/g, json ? '\\u003C!--' : '\\x3C!--');
+	}
+	if (options.wrap) {
+		result = quote + result + quote;
+	}
+	return result;
+};
+
+jsesc.version = '3.0.2';
+
+module.exports = jsesc;
Index: frontend/node_modules/jsesc/man/jsesc.1
===================================================================
--- frontend/node_modules/jsesc/man/jsesc.1	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/man/jsesc.1	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,94 @@
+.Dd May 13, 2016
+.Dt jsesc 1
+.Sh NAME
+.Nm jsesc
+.Nd escape strings for use in JavaScript string literals
+.Sh SYNOPSIS
+.Nm
+.Op Fl s | -single-quotes Ar string
+.br
+.Op Fl d | -double-quotes Ar string
+.br
+.Op Fl w | -wrap Ar string
+.br
+.Op Fl e | -escape-everything Ar string
+.br
+.Op Fl 6 | -es6 Ar string
+.br
+.Op Fl l | -lowercase-hex Ar string
+.br
+.Op Fl j | -json Ar string
+.br
+.Op Fl p | -object Ar string
+.br
+.Op Fl p | -pretty Ar string
+.br
+.Op Fl v | -version
+.br
+.Op Fl h | -help
+.Sh DESCRIPTION
+.Nm
+escapes strings for use in JavaScript string literals while generating the shortest possible valid ASCII-only output.
+.Sh OPTIONS
+.Bl -ohang -offset
+.It Sy "-s, --single-quotes"
+Escape any occurrences of ' in the input string as \\', so that the output can be used in a JavaScript string literal wrapped in single quotes.
+.It Sy "-d, --double-quotes"
+Escape any occurrences of " in the input string as \\", so that the output can be used in a JavaScript string literal wrapped in double quotes.
+.It Sy "-w, --wrap"
+Make sure the output is a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified using the
+.Ar -s | --single-quotes
+or
+.Ar -d | --double-quotes
+settings.
+.It Sy "-6, --es6"
+Escape any astral Unicode symbols using ECMAScript 6 Unicode code point escape sequences.
+.It Sy "-e, --escape-everything"
+Escape all the symbols in the output, even printable ASCII symbols.
+.It Sy "-j, --json"
+Make sure the output is valid JSON. Hexadecimal character escape sequences and the \\v or \\0 escape sequences will not be used. Setting this flag enables the
+.Ar -d | --double-quotes
+and
+.Ar -w | --wrap
+settings.
+.It Sy "-o, --object"
+Treat the input as a JavaScript object rather than a string. Accepted values are flat arrays containing only string values, and flat objects containing only string values.
+.It Sy "-p, --pretty"
+Pretty-print the output for objects, using whitespace to make it more readable. Setting this flag enables the
+.It Sy "-l, --lowercase-hex"
+Use lowercase for alphabetical hexadecimal digits in escape sequences.
+.Ar -o | --object
+setting.
+.It Sy "-v, --version"
+Print jsesc's version.
+.It Sy "-h, --help"
+Show the help screen.
+.El
+.Sh EXIT STATUS
+The
+.Nm jsesc
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width flag -compact
+.It Li 0
+.Nm
+successfully escaped the given string and printed the result.
+.It Li 1
+.Nm
+wasn't instructed to escape anything (for example, the
+.Ar --help
+flag was set); or, an error occurred.
+.El
+.Sh EXAMPLES
+.Bl -ohang -offset
+.It Sy "jsesc 'foo bar baz'"
+Print an escaped version of the given string.
+.It Sy echo\ 'foo bar baz'\ |\ jsesc
+Print an escaped version of the string that gets piped in.
+.El
+.Sh BUGS
+jsesc's bug tracker is located at <https://github.com/mathiasbynens/jsesc/issues>.
+.Sh AUTHOR
+Mathias Bynens <https://mathiasbynens.be/>
+.Sh WWW
+<https://mths.be/jsesc>
Index: frontend/node_modules/jsesc/package.json
===================================================================
--- frontend/node_modules/jsesc/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/jsesc/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,56 @@
+{
+  "name": "jsesc",
+  "version": "3.1.0",
+  "description": "Given some data, jsesc returns the shortest possible stringified & ASCII-safe representation of that data.",
+  "homepage": "https://mths.be/jsesc",
+  "engines": {
+    "node": ">=6"
+  },
+  "main": "jsesc.js",
+  "bin": "bin/jsesc",
+  "man": "man/jsesc.1",
+  "keywords": [
+    "buffer",
+    "escape",
+    "javascript",
+    "json",
+    "map",
+    "set",
+    "string",
+    "stringify",
+    "tool"
+  ],
+  "license": "MIT",
+  "author": {
+    "name": "Mathias Bynens",
+    "url": "https://mathiasbynens.be/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/mathiasbynens/jsesc.git"
+  },
+  "bugs": "https://github.com/mathiasbynens/jsesc/issues",
+  "files": [
+    "LICENSE-MIT.txt",
+    "jsesc.js",
+    "bin/",
+    "man/"
+  ],
+  "scripts": {
+    "build": "grunt template",
+    "coveralls": "istanbul cover --verbose --dir 'coverage' 'tests/tests.js' && coveralls < coverage/lcov.info'",
+    "cover": "istanbul cover --report 'html' --verbose --dir 'coverage' 'tests/tests.js'",
+    "test": "mocha tests"
+  },
+  "devDependencies": {
+    "coveralls": "^2.11.6",
+    "grunt": "^0.4.5",
+    "grunt-cli": "^1.3.2",
+    "grunt-template": "^0.2.3",
+    "istanbul": "^0.4.2",
+    "mocha": "^5.2.0",
+    "regenerate": "^1.3.0",
+    "requirejs": "^2.1.22",
+    "unicode-13.0.0": "0.8.0"
+  }
+}
