From 06500063d5131221aab241db9eab7c1533548db2 Mon Sep 17 00:00:00 2001 From: Chris Watson Date: Fri, 3 Jan 2020 16:29:48 -0700 Subject: [PATCH 1/5] Add HTMLParser --- gramjs/Utils.js | 6 +- gramjs/extensions/HTML.js | 269 ++++++++++++++++++++++++++++++++++ gramjs/extensions/Markdown.js | 35 +++-- gramjs/extensions/Scanner.js | 4 +- gramjs/extensions/index.js | 14 +- 5 files changed, 307 insertions(+), 21 deletions(-) create mode 100644 gramjs/extensions/HTML.js diff --git a/gramjs/Utils.js b/gramjs/Utils.js index 0d9e7edf..8a9d4fbb 100644 --- a/gramjs/Utils.js +++ b/gramjs/Utils.js @@ -1,7 +1,7 @@ const path = require('path') const mime = require('mime-types') const struct = require('python-struct') -const { MarkdownParser, HTMLParser } = require('./extensions') +const { markdown, html } = require('./extensions') const { types } = require('./tl') const USERNAME_RE = new RegExp('@|(?:https?:\\/\\/)?(?:www\\.)?' + @@ -892,10 +892,10 @@ function sanitizeParseMode(mode) { switch (mode.toLowerCase()) { case 'md': case 'markdown': - return MarkdownParser + return markdown case 'htm': case 'html': - return HTMLParser + return html default: throw new Error(`Unknown parse mode ${mode}`) } diff --git a/gramjs/extensions/HTML.js b/gramjs/extensions/HTML.js new file mode 100644 index 00000000..b841a698 --- /dev/null +++ b/gramjs/extensions/HTML.js @@ -0,0 +1,269 @@ +/* eslint-disable no-extend-native */ +/* eslint-disable no-case-declarations, no-fallthrough */ +const Scanner = require('./Scanner') +const { + MessageEntityBold, MessageEntityItalic, MessageEntityCode, + MessageEntityPre, MessageEntityEmail, MessageEntityTextUrl, + MessageEntityUnderline, MessageEntityStrike, MessageEntityBlockquote, +} = require('../tl/types') + +class HTMLParser extends Scanner { + constructor(str) { + super(str) + this.text = '' + this.entities = [] + this._buildingEntities = {} + this._openTags = [] + this._openTagsMeta = [] + } + + parse() { + while (!this.eof()) { + switch (this.peek(1)) { + case '<': + this.consume(1) + if (this.peek(1) === '/') { + // Closing tag + this.consume(1) + const tag = this.scanUntil('>').trim() + + // Consume the closing bracket + this.consume(1) + + this.handleEndTag(tag) + } else { + // Opening tag + let tag = this.scanUntil('>').trim() + let attrs + + // Consume the closing bracket + this.consume(1); + + [tag, ...attrs] = tag.split(/\s+/) + attrs = attrs + // Split on `=` + .map((a) => a.split('=')) + // Take non key/value items and make them `true` + .map((a) => a.length === 1 ? a.concat([true]) : a) + // Remove quotes if they exist + .map((a) => { + const txt = a[0].replace(/^('|")|('|")$/, '') + return [txt, a[1]] + }) + + this.handleStartTag(tag, attrs) + } + break + default: + if (this.eof()) break + this.handleData(this.chr) + this.pos += 1 + } + } + + return [this.text, this.entities] + } + + static unparse(text, entities, _offset = 0, _length = null) { + if (!_length) { + _length = text.length + } + + const html = [] + let lastOffset = 0 + + for (const [i, entity] of entities.entries()) { + if (entity.offset > _offset + _length) { + break + } + + const relativeOffset = entity.offset - _offset + if (relativeOffset > lastOffset) { + html.push(text.substring(lastOffset, relativeOffset)) + } else if (relativeOffset < lastOffset) { + continue + } + + let skipEntity = false + let length = entity.length + + while ((relativeOffset < _length) && + ('\ud800' <= text.substring(relativeOffset, length)) && + (text.substring(relativeOffset, length) <= '\udfff')) { + length += 1 + } + + const entityText = this.unparse( + text.substring(relativeOffset, relativeOffset + length), + entities.slice(i + 1, entities.length), + entity.offset, + length, + ) + + const entityType = entity.constructor.name + + switch (entityType) { + case 'MessageEntityBold': + html.push(`${entityText}`) + break + case 'MessageEntityItalic': + html.push(`${entityText}`) + break + case 'MessageEntityCode': + html.push(`${entityText}`) + break + case 'MessageEntityUnderline': + html.push(`${entityText}`) + break + case 'MessageEntityStrike': + html.push(`${entityText}`) + break + case 'MessageEntityBlockquote': + html.push(`
${entityText}
`) + break + case 'MessageEntityPre': + if (entity.language) { + html.push(`
+                      
+                        ${entityText}
+                      
+                    
`) + } else { + html.push(`
${entityText}
`) + } + break + case 'MessageEntityEmail': + html.push(`${entityText}`) + break + case 'MessageEntityUrl': + html.push(`${entityText}`) + break + case 'MessageEntityTextUrl': + html.push(`${entityText}`) + break + case 'MessageEntityMentionName': + html.push(`${entityText}`) + break + default: + skipEntity = true + } + + lastOffset = relativeOffset + (skipEntity ? 0 : length) + } + + while ((lastOffset < _length) && + ('\ud800' <= text.substring(lastOffset)) && + (text.substring(lastOffset) <= '\udfff')) { + lastOffset += 1 + } + + html.push(text.substring(lastOffset, text.length)) + return html.join('') + } + + handleStartTag(tag, attrs = {}) { + this._openTags.unshift(tag) + this._openTagsMeta.unshift(null) + + let EntityType + const args = {} + + switch (tag) { + case 'b': + case 'strong': + EntityType = MessageEntityBold + break + case 'i': + case 'em': + EntityType = MessageEntityItalic + break + case 'u': + EntityType = MessageEntityUnderline + break + case 's': + case 'del': + EntityType = MessageEntityStrike + break + case 'blockquote': + EntityType = MessageEntityBlockquote + break + case 'code': + // If we're in the middle of a
 tag, this  tag is
+            // probably intended for syntax highlighting.
+            //
+            // Syntax highlighting is set with
+            //     codeblock
+            // inside 
 tags
+            const pre = this._buildingEntities['pre']
+            const language = attrs['class'] ? attrs['class'].match(/language-(\S+)/)[1] : null
+            if (pre && language) {
+                pre.language = language
+            } else {
+                EntityType = MessageEntityCode
+            }
+            break
+        case 'pre':
+            EntityType = MessageEntityPre
+            args['language'] = ''
+            break
+        case 'a':
+            let url = attrs['href']
+            if (!url) return
+
+            if (url.indexOf('mailto:') === 0) {
+                EntityType = MessageEntityEmail
+            } else {
+                EntityType = MessageEntityTextUrl
+                args['url'] = url
+                url = null
+            }
+
+            this._openTagsMeta.shift()
+            this._openTagsMeta.unshift(url)
+            break
+        default:
+            // Do nothing
+        }
+
+        if (EntityType && !(tag in this._buildingEntities)) {
+            this._buildingEntities[tag] = new EntityType({
+                offset: this.text.length,
+                // The length will be determined when closing the tag.
+                length: 0,
+                ...args,
+            })
+        }
+    }
+
+    handleData(text) {
+        for (const [, entity] of Object.entries(this._buildingEntities)) {
+            entity.length += text.length
+        }
+
+        this.text += text
+    }
+
+    handleEndTag(tag) {
+        this._openTags.shift()
+        this._openTagsMeta.shift()
+
+        const entity = this._buildingEntities[tag]
+        if (entity) {
+            delete this._buildingEntities[tag]
+            this.entities.push(entity)
+        }
+    }
+}
+
+const parse = (str) => {
+    const parser = new HTMLParser(str)
+    return parser.parse()
+}
+
+const unparse = HTMLParser.unparse
+
+module.exports = {
+    HTMLParser,
+    parse,
+    unparse,
+}
diff --git a/gramjs/extensions/Markdown.js b/gramjs/extensions/Markdown.js
index 1a07091a..581380c8 100644
--- a/gramjs/extensions/Markdown.js
+++ b/gramjs/extensions/Markdown.js
@@ -19,17 +19,17 @@ const DELIMITERS = {
 class MarkdownParser extends Scanner {
     constructor(str) {
         super(str)
-        this.stripped = ''
+        this.text = ''
         this.entities = []
     }
 
-    get strippedPos() {
-        return this.stripped.length - 1
+    get textPos() {
+        return this.text.length - 1
     }
 
     parse() {
         // Do a little reset
-        this.stripped = ''
+        this.text = ''
         this.entities = []
 
         while (!this.eof()) {
@@ -55,12 +55,12 @@ class MarkdownParser extends Scanner {
             case '[':
                 if (this.parseURL()) break
             default:
-                this.stripped += this.chr
+                this.text += this.chr
                 this.pos += 1
             }
         }
 
-        return [this.stripped, this.entities]
+        return [this.text, this.entities]
     }
 
     static unparse(text, entities) {
@@ -107,8 +107,8 @@ class MarkdownParser extends Scanner {
 
     parseEntity(EntityType, delimiter) {
         // The offset for this entity should be the end of the
-        // stripped string
-        const offset = this.strippedPos
+        // text string
+        const offset = this.textPos
 
         // Consume the delimiter
         this.consume(delimiter.length)
@@ -121,8 +121,8 @@ class MarkdownParser extends Scanner {
             // Consume the delimiter again
             this.consume(delimiter.length)
 
-            // Add the entire content to the stripped content
-            this.stripped += content
+            // Add the entire content to the text
+            this.text += content
 
             // Create and return a new Entity
             const entity = new EntityType({
@@ -141,7 +141,7 @@ class MarkdownParser extends Scanner {
         const [full, txt, url] = match
         const len = full.length
 
-        this.stripped += txt
+        this.text += txt
 
         const entity = new MessageEntityTextUrl({
             offset: this.pos,
@@ -156,4 +156,15 @@ class MarkdownParser extends Scanner {
     }
 }
 
-module.exports = MarkdownParser
+const parse = (str) => {
+    const parser = new MarkdownParser(str)
+    return parser.parse()
+}
+
+const unparse = MarkdownParser.unparse
+
+module.exports = {
+    MarkdownParser,
+    parse,
+    unparse,
+}
diff --git a/gramjs/extensions/Scanner.js b/gramjs/extensions/Scanner.js
index 9599e44b..59af3288 100644
--- a/gramjs/extensions/Scanner.js
+++ b/gramjs/extensions/Scanner.js
@@ -41,11 +41,11 @@ class Scanner {
     }
 
     bof() {
-        return this.pos === 0
+        return this.pos <= 0
     }
 
     eof() {
-        return this.pos === this.str.length
+        return this.pos >= this.str.length
     }
 }
 
diff --git a/gramjs/extensions/index.js b/gramjs/extensions/index.js
index a67506b5..bec6e657 100644
--- a/gramjs/extensions/index.js
+++ b/gramjs/extensions/index.js
@@ -6,8 +6,8 @@ const MessagePacker = require('./MessagePacker')
 const AsyncQueue = require('./AsyncQueue')
 const PromisedNetSocket = require('./PromisedNetSockets')
 const Scanner = require('./Scanner')
-const MarkdownParser = require('./Markdown')
-const HTMLParser = null
+const markdown = require('./Markdown')
+const html = require('./HTML')
 
 module.exports = {
     BinaryWriter,
@@ -18,6 +18,12 @@ module.exports = {
     PromisedWebSockets,
     PromisedNetSocket,
     Scanner,
-    MarkdownParser,
-    HTMLParser,
+    markdown: {
+        parse: markdown.parse,
+        unparse: markdown.unparse,
+    },
+    html: {
+        parse: html.parse,
+        unparse: html.unparse,
+    }
 }

From 18a8b47c9e63e54745f743327e73ab7a331635f4 Mon Sep 17 00:00:00 2001
From: Chris Watson 
Date: Sat, 4 Jan 2020 17:07:19 -0700
Subject: [PATCH 2/5] Refactor and add specs for Scanner/MarkdownParser

---
 .gitignore                                  |    1 +
 __tests__/{ => crypto}/AES.spec.js          |    4 +-
 __tests__/{ => crypto}/calcKey.spec.js      |    2 +-
 __tests__/{ => crypto}/factorizator.spec.js |    2 +-
 __tests__/{ => crypto}/readBuffer.spec.js   |    2 +-
 __tests__/extensions/Markdown.spec.js       |   95 ++
 __tests__/extensions/Scanner.spec.js        |  100 ++
 gramjs/extensions/Markdown.js               |   19 +-
 gramjs/extensions/Scanner.js                |   12 +-
 jest.config.js                              |  264 +--
 package-lock.json                           | 1596 +++++++++++++++----
 11 files changed, 1663 insertions(+), 434 deletions(-)
 rename __tests__/{ => crypto}/AES.spec.js (95%)
 rename __tests__/{ => crypto}/calcKey.spec.js (95%)
 rename __tests__/{ => crypto}/factorizator.spec.js (87%)
 rename __tests__/{ => crypto}/readBuffer.spec.js (98%)
 create mode 100644 __tests__/extensions/Markdown.spec.js
 create mode 100644 __tests__/extensions/Scanner.spec.js

diff --git a/.gitignore b/.gitignore
index 8e0b70de..1229dae0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
 /gramjs/tl/AllTLObjects.js
 /gramjs/errors/RPCErrorList.js
 /dist/
+/coverage/
 
 # User session
 *.session
diff --git a/__tests__/AES.spec.js b/__tests__/crypto/AES.spec.js
similarity index 95%
rename from __tests__/AES.spec.js
rename to __tests__/crypto/AES.spec.js
index bf5f149c..41d38564 100644
--- a/__tests__/AES.spec.js
+++ b/__tests__/crypto/AES.spec.js
@@ -1,5 +1,5 @@
-const AES = require('../gramjs/crypto/AES')
-const AESModeCTR = require('../gramjs/crypto/AESCTR')
+const AES = require('../../gramjs/crypto/AES')
+const AESModeCTR = require('../../gramjs/crypto/AESCTR')
 describe('IGE encrypt function', () => {
     test('it should return 4a657a834edc2956ec95b2a42ec8c1f2d1f0a6028ac26fd830ed23855574b4e69dd1a2be2ba18a53a49b879b2' +
         '45e1065e14b6e8ac5ba9b24befaff3209b77b5f', () => {
diff --git a/__tests__/calcKey.spec.js b/__tests__/crypto/calcKey.spec.js
similarity index 95%
rename from __tests__/calcKey.spec.js
rename to __tests__/crypto/calcKey.spec.js
index c96a369f..ce662163 100644
--- a/__tests__/calcKey.spec.js
+++ b/__tests__/crypto/calcKey.spec.js
@@ -1,4 +1,4 @@
-const MTProtoState = require('../gramjs/network/MTProtoState')
+const MTProtoState = require('../../gramjs/network/MTProtoState')
 
 describe('calcKey function', () => {
     test('it should return 0x93355e3f1f50529b6fb93eaf97f29b69c16345f53621e9d45cd9a11ddfbebac9 and' +
diff --git a/__tests__/factorizator.spec.js b/__tests__/crypto/factorizator.spec.js
similarity index 87%
rename from __tests__/factorizator.spec.js
rename to __tests__/crypto/factorizator.spec.js
index e469ed7c..42fdd2ae 100644
--- a/__tests__/factorizator.spec.js
+++ b/__tests__/crypto/factorizator.spec.js
@@ -1,4 +1,4 @@
-const Factorizator = require('../gramjs/crypto/Factorizator')
+const Factorizator = require('../../gramjs/crypto/Factorizator')
 
 describe('calcKey function', () => {
     test('it should return 0x20a13b25e1726bfc', () => {
diff --git a/__tests__/readBuffer.spec.js b/__tests__/crypto/readBuffer.spec.js
similarity index 98%
rename from __tests__/readBuffer.spec.js
rename to __tests__/crypto/readBuffer.spec.js
index 6ff660f1..e290af3c 100644
--- a/__tests__/readBuffer.spec.js
+++ b/__tests__/crypto/readBuffer.spec.js
@@ -1,4 +1,4 @@
-const Helpers = require('../gramjs/Helpers')
+const Helpers = require('../../gramjs/Helpers')
 
 describe('readBufferFromBigInt 8 bytes function', () => {
     test('it should return 0x20a13b25e1726bfc', () => {
diff --git a/__tests__/extensions/Markdown.spec.js b/__tests__/extensions/Markdown.spec.js
new file mode 100644
index 00000000..953844b5
--- /dev/null
+++ b/__tests__/extensions/Markdown.spec.js
@@ -0,0 +1,95 @@
+const { MarkdownParser } = require('../../gramjs/extensions/Markdown')
+const types = require('../../gramjs/tl/types')
+
+describe('MarkdownParser', () => {
+    test('it should construct a new MarkdownParser', () => {
+        const parser = new MarkdownParser('Hello world')
+        expect(parser.text).toEqual('')
+        expect(parser.entities).toEqual([])
+    })
+
+    describe('.parse', () => {
+        test('it should parse bold entities', () => {
+            const parser = new MarkdownParser('Hello **world**')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityBold)
+        })
+
+        test('it should parse italic entities', () => {
+            const parser = new MarkdownParser('Hello __world__')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityItalic)
+        })
+
+        test('it should parse code entities', () => {
+            const parser = new MarkdownParser('Hello `world`')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityCode)
+        })
+
+        test('it should parse pre entities', () => {
+            const parser = new MarkdownParser('Hello ```world```')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityPre)
+        })
+
+        test('it should parse strike entities', () => {
+            const parser = new MarkdownParser('Hello ~~world~~')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityStrike)
+        })
+
+        test('it should parse link entities', () => {
+            const parser = new MarkdownParser('Hello [world](https://hello.world)')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityTextUrl)
+            expect(entities[0].url).toEqual('https://hello.world')
+        })
+
+        test('it should not parse nested entities', () => {
+            const parser = new MarkdownParser('Hello **__world__**')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello __world__')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityBold)
+        })
+
+        test('it should parse multiple entities', () => {
+            const parser = new MarkdownParser('__Hello__ **world**')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(2)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityItalic)
+            expect(entities[1]).toBeInstanceOf(types.MessageEntityBold)
+        })
+    })
+
+    describe('.unparse', () => {
+        test('it should create a markdown string from raw text and entities', () => {
+            const unparsed = '**hello** __hello__ ~~hello~~ `hello` ```hello``` [hello](https://hello.world)'
+            const strippedText = 'hello hello hello hello hello hello'
+            const rawEntities = [
+                new types.MessageEntityBold({ offset: 0, length: 5 }),
+                new types.MessageEntityItalic({ offset: 6, length: 5 }),
+                new types.MessageEntityStrike({ offset: 12, length: 5 }),
+                new types.MessageEntityCode({ offset: 18, length: 5 }),
+                new types.MessageEntityPre({ offset: 24, length: 5 }),
+                new types.MessageEntityTextUrl({ offset: 30, length: 5, url: 'https://hello.world' }),
+            ]
+            const text = MarkdownParser.unparse(strippedText, rawEntities)
+            expect(text).toEqual(unparsed)
+        })
+    })
+})
diff --git a/__tests__/extensions/Scanner.spec.js b/__tests__/extensions/Scanner.spec.js
new file mode 100644
index 00000000..282ee745
--- /dev/null
+++ b/__tests__/extensions/Scanner.spec.js
@@ -0,0 +1,100 @@
+const Scanner = require('../../gramjs/extensions/Scanner')
+
+const helloScanner = new Scanner('Hello world')
+
+describe('Scanner', () => {
+    beforeEach(() => helloScanner.reset())
+
+    test('it should construct a new Scanner', () => {
+        expect(helloScanner.str).toEqual('Hello world')
+        expect(helloScanner.pos).toEqual(0)
+        expect(helloScanner.lastMatch).toBeNull()
+    })
+
+    describe('.chr', () => {
+        test('it should return the character at the current pos', () => {
+            expect(helloScanner.chr).toEqual('H')
+        })
+    })
+
+    describe('.peek', () => {
+        test('it should return the character at the current pos', () => {
+            expect(helloScanner.peek()).toEqual('H')
+        })
+
+        test('it should return the next n characters', () => {
+            expect(helloScanner.peek(3)).toEqual('Hel')
+            expect(helloScanner.peek(5)).toEqual('Hello')
+        })
+    })
+
+    describe('.consume', () => {
+        test('it should consume the current character', () => {
+            const char = helloScanner.consume()
+            expect(char).toEqual('H')
+            expect(helloScanner.pos).toEqual(1)
+        })
+
+        test('it should consume the next n characters', () => {
+            const chars = helloScanner.consume(5)
+            expect(chars).toEqual('Hello')
+            expect(helloScanner.pos).toEqual(5)
+        })
+    })
+
+    describe('.reverse', () => {
+        test('it should set pos back n characters', () => {
+            helloScanner.consume(5)
+            helloScanner.reverse(5)
+            expect(helloScanner.pos).toEqual(0)
+        })
+
+        test('it should not go back further than 0', () => {
+            helloScanner.reverse(10)
+            expect(helloScanner.pos).toEqual(0)
+        })
+    })
+
+    describe('.scanUntil', () => {
+        test('it should scan the string for a regular expression starting at the current pos', () => {
+            helloScanner.scanUntil(/w/)
+            expect(helloScanner.pos).toEqual(6)
+        })
+
+        test('it should do nothing if the pattern is not found', () => {
+            helloScanner.scanUntil(/G/)
+            expect(helloScanner.pos).toEqual(0)
+        })
+    })
+
+    describe('.rest', () => {
+        test('it should return the unconsumed input', () => {
+            helloScanner.consume(6)
+            expect(helloScanner.rest).toEqual('world')
+        })
+    })
+
+    describe('.reset', () => {
+        test('it should reset the pos to 0', () => {
+            helloScanner.consume(5)
+            helloScanner.reset()
+            expect(helloScanner.pos).toEqual(0)
+        })
+    })
+
+    describe('.eof', () => {
+        test('it should return true if the scanner has reached the end of the input', () => {
+            expect(helloScanner.eof()).toBe(false)
+            helloScanner.consume(11)
+            expect(helloScanner.eof()).toBe(true)
+        })
+    })
+
+    describe('.bof', () => {
+        test('it should return true if pos is 0', () => {
+            expect(helloScanner.bof()).toBe(true)
+            helloScanner.consume(11)
+            expect(helloScanner.bof()).toBe(false)
+        })
+    })
+})
diff --git a/gramjs/extensions/Markdown.js b/gramjs/extensions/Markdown.js
index 581380c8..24eb0b36 100644
--- a/gramjs/extensions/Markdown.js
+++ b/gramjs/extensions/Markdown.js
@@ -11,7 +11,7 @@ const URL_RE = /\[([\S\s]+?)\]\((.+?)\)/
 const DELIMITERS = {
     'MessageEntityBold': '**',
     'MessageEntityItalic': '__',
-    'MessageEntityCode': '``',
+    'MessageEntityCode': '`',
     'MessageEntityPre': '```',
     'MessageEntityStrike': '~~',
 }
@@ -23,10 +23,6 @@ class MarkdownParser extends Scanner {
         this.entities = []
     }
 
-    get textPos() {
-        return this.text.length - 1
-    }
-
     parse() {
         // Do a little reset
         this.text = ''
@@ -49,8 +45,8 @@ class MarkdownParser extends Scanner {
             case '`':
                 if (this.peek(3) == '```') {
                     if (this.parseEntity(MessageEntityPre, '```')) break
-                } else if (this.peek(2) == '``') {
-                    if (this.parseEntity(MessageEntityCode, '``')) break
+                } else if (this.peek(1) == '`') {
+                    if (this.parseEntity(MessageEntityCode, '`')) break
                 }
             case '[':
                 if (this.parseURL()) break
@@ -71,15 +67,15 @@ class MarkdownParser extends Scanner {
         for (const entity of entities) {
             const s = entity.offset
             const e = entity.offset + entity.length
-            const delimiter = DELIMITERS[typeof(entity)]
+            const delimiter = DELIMITERS[entity.constructor.name]
             if (delimiter) {
                 insertAt.push([s, delimiter])
                 insertAt.push([e, delimiter])
             } else {
                 let url = null
-
                 if (entity instanceof MessageEntityTextUrl) {
                     url = entity.url
+                    console.log(url)
                 } else if (entity instanceof MessageEntityMentionName) {
                     url = `tg://user?id=${entity.userId}`
                 }
@@ -108,7 +104,7 @@ class MarkdownParser extends Scanner {
     parseEntity(EntityType, delimiter) {
         // The offset for this entity should be the end of the
         // text string
-        const offset = this.textPos
+        const offset = this.text.length
 
         // Consume the delimiter
         this.consume(delimiter.length)
@@ -140,11 +136,12 @@ class MarkdownParser extends Scanner {
 
         const [full, txt, url] = match
         const len = full.length
+        const offset = this.text.length
 
         this.text += txt
 
         const entity = new MessageEntityTextUrl({
-            offset: this.pos,
+            offset: offset,
             length: txt.length,
             url: url,
         })
diff --git a/gramjs/extensions/Scanner.js b/gramjs/extensions/Scanner.js
index 59af3288..fc2d0b49 100644
--- a/gramjs/extensions/Scanner.js
+++ b/gramjs/extensions/Scanner.js
@@ -15,7 +15,7 @@ class Scanner {
 
     reverse(n = 1) {
         const pos = this.pos - n
-        return pos < 0 ? 0 : pos
+        this.pos = pos < 0 ? 0 : pos
     }
 
     consume(n = 1) {
@@ -23,7 +23,13 @@ class Scanner {
     }
 
     scanUntil(re, consumeMatch = false) {
-        const match = this.lastMatch = this.rest.match(re)
+        let match
+        try {
+            match = this.lastMatch = this.rest.match(re)
+        } catch {
+            match = null
+        }
+
         if (!match) return null
 
         let len = match.index
@@ -33,7 +39,7 @@ class Scanner {
     }
 
     get rest() {
-        return this.str.slice(this.pos, this.str.length)
+        return this.str.slice(this.pos, this.str.length) || null
     }
 
     reset() {
diff --git a/jest.config.js b/jest.config.js
index 6dc4fff6..f5adf092 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,187 +2,187 @@
 // https://jestjs.io/docs/en/configuration.html
 
 module.exports = {
-  // All imported modules in your tests should be mocked automatically
-  // automock: false,
+    // All imported modules in your tests should be mocked automatically
+    // automock: false,
 
-  // Stop running tests after `n` failures
-  // bail: 0,
+    // Stop running tests after `n` failures
+    // bail: 0,
 
-  // Respect "browser" field in package.json when resolving modules
-  // browser: false,
+    // Respect "browser" field in package.json when resolving modules
+    // browser: false,
 
-  // The directory where Jest should store its cached dependency information
-  // cacheDirectory: "C:\\Users\\painor\\AppData\\Local\\Temp\\jest",
+    // The directory where Jest should store its cached dependency information
+    // cacheDirectory: "C:\\Users\\painor\\AppData\\Local\\Temp\\jest",
 
-  // Automatically clear mock calls and instances between every test
-  clearMocks: true,
+    // Automatically clear mock calls and instances between every test
+    clearMocks: true,
 
-  // Indicates whether the coverage information should be collected while executing the test
-  // collectCoverage: false,
+    // Indicates whether the coverage information should be collected while executing the test
+    // collectCoverage: false,
 
-  // An array of glob patterns indicating a set of files for which coverage information should be collected
-  // collectCoverageFrom: null,
+    // An array of glob patterns indicating a set of files for which coverage information should be collected
+    // collectCoverageFrom: null,
 
-  // The directory where Jest should output its coverage files
-  coverageDirectory: "coverage",
+    // The directory where Jest should output its coverage files
+    coverageDirectory: 'coverage',
 
-  // An array of regexp pattern strings used to skip coverage collection
-  // coveragePathIgnorePatterns: [
-  //   "\\\\node_modules\\\\"
-  // ],
+    // An array of regexp pattern strings used to skip coverage collection
+    // coveragePathIgnorePatterns: [
+    //   "\\\\node_modules\\\\"
+    // ],
 
-  // A list of reporter names that Jest uses when writing coverage reports
-  // coverageReporters: [
-  //   "json",
-  //   "text",
-  //   "lcov",
-  //   "clover"
-  // ],
+    // A list of reporter names that Jest uses when writing coverage reports
+    // coverageReporters: [
+    //   "json",
+    //   "text",
+    //   "lcov",
+    //   "clover"
+    // ],
 
-  // An object that configures minimum threshold enforcement for coverage results
-  // coverageThreshold: null,
+    // An object that configures minimum threshold enforcement for coverage results
+    // coverageThreshold: null,
 
-  // A path to a custom dependency extractor
-  // dependencyExtractor: null,
+    // A path to a custom dependency extractor
+    // dependencyExtractor: null,
 
-  // Make calling deprecated APIs throw helpful error messages
-  // errorOnDeprecated: false,
+    // Make calling deprecated APIs throw helpful error messages
+    // errorOnDeprecated: false,
 
-  // Force coverage collection from ignored files using an array of glob patterns
-  // forceCoverageMatch: [],
+    // Force coverage collection from ignored files using an array of glob patterns
+    // forceCoverageMatch: [],
 
-  // A path to a module which exports an async function that is triggered once before all test suites
-  // globalSetup: null,
+    // A path to a module which exports an async function that is triggered once before all test suites
+    // globalSetup: null,
 
-  // A path to a module which exports an async function that is triggered once after all test suites
-  // globalTeardown: null,
+    // A path to a module which exports an async function that is triggered once after all test suites
+    // globalTeardown: null,
 
-  // A set of global variables that need to be available in all test environments
-  // globals: {},
+    // A set of global variables that need to be available in all test environments
+    // globals: {},
 
-  // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
-  // maxWorkers: "50%",
+    // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
+    // maxWorkers: "50%",
 
-  // An array of directory names to be searched recursively up from the requiring module's location
-  // moduleDirectories: [
-  //   "node_modules"
-  // ],
+    // An array of directory names to be searched recursively up from the requiring module's location
+    // moduleDirectories: [
+    //   "node_modules"
+    // ],
 
-  // An array of file extensions your modules use
-  // moduleFileExtensions: [
-  //   "js",
-  //   "json",
-  //   "jsx",
-  //   "ts",
-  //   "tsx",
-  //   "node"
-  // ],
+    // An array of file extensions your modules use
+    // moduleFileExtensions: [
+    //   "js",
+    //   "json",
+    //   "jsx",
+    //   "ts",
+    //   "tsx",
+    //   "node"
+    // ],
 
-  // A map from regular expressions to module names that allow to stub out resources with a single module
-  // moduleNameMapper: {},
+    // A map from regular expressions to module names that allow to stub out resources with a single module
+    // moduleNameMapper: {},
 
-  // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
-  // modulePathIgnorePatterns: [],
+    // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
+    // modulePathIgnorePatterns: [],
 
-  // Activates notifications for test results
-  // notify: false,
+    // Activates notifications for test results
+    // notify: false,
 
-  // An enum that specifies notification mode. Requires { notify: true }
-  // notifyMode: "failure-change",
+    // An enum that specifies notification mode. Requires { notify: true }
+    // notifyMode: "failure-change",
 
-  // A preset that is used as a base for Jest's configuration
-  // preset: null,
+    // A preset that is used as a base for Jest's configuration
+    // preset: null,
 
-  // Run tests from one or more projects
-  // projects: null,
+    // Run tests from one or more projects
+    // projects: null,
 
-  // Use this configuration option to add custom reporters to Jest
-  // reporters: undefined,
+    // Use this configuration option to add custom reporters to Jest
+    // reporters: undefined,
 
-  // Automatically reset mock state between every test
-  // resetMocks: false,
+    // Automatically reset mock state between every test
+    // resetMocks: false,
 
-  // Reset the module registry before running each individual test
-  // resetModules: false,
+    // Reset the module registry before running each individual test
+    // resetModules: false,
 
-  // A path to a custom resolver
-  // resolver: null,
+    // A path to a custom resolver
+    // resolver: null,
 
-  // Automatically restore mock state between every test
-  // restoreMocks: false,
+    // Automatically restore mock state between every test
+    // restoreMocks: false,
 
-  // The root directory that Jest should scan for tests and modules within
-  // rootDir: null,
+    // The root directory that Jest should scan for tests and modules within
+    // rootDir: null,
 
-  // A list of paths to directories that Jest should use to search for files in
-  // roots: [
-  //   ""
-  // ],
+    // A list of paths to directories that Jest should use to search for files in
+    // roots: [
+    //   ""
+    // ],
 
-  // Allows you to use a custom runner instead of Jest's default test runner
-  // runner: "jest-runner",
+    // Allows you to use a custom runner instead of Jest's default test runner
+    // runner: "jest-runner",
 
-  // The paths to modules that run some code to configure or set up the testing environment before each test
-  // setupFiles: [],
+    // The paths to modules that run some code to configure or set up the testing environment before each test
+    // setupFiles: [],
 
-  // A list of paths to modules that run some code to configure or set up the testing framework before each test
-  // setupFilesAfterEnv: [],
+    // A list of paths to modules that run some code to configure or set up the testing framework before each test
+    // setupFilesAfterEnv: [],
 
-  // A list of paths to snapshot serializer modules Jest should use for snapshot testing
-  // snapshotSerializers: [],
+    // A list of paths to snapshot serializer modules Jest should use for snapshot testing
+    // snapshotSerializers: [],
 
-  // The test environment that will be used for testing
-  testEnvironment: "node",
+    // The test environment that will be used for testing
+    testEnvironment: 'node',
 
-  // Options that will be passed to the testEnvironment
-  // testEnvironmentOptions: {},
+    // Options that will be passed to the testEnvironment
+    // testEnvironmentOptions: {},
 
-  // Adds a location field to test results
-  // testLocationInResults: false,
+    // Adds a location field to test results
+    // testLocationInResults: false,
 
-  // The glob patterns Jest uses to detect test files
-  // testMatch: [
-  //   "**/__tests__/**/*.[jt]s?(x)",
-  //   "**/?(*.)+(spec|test).[tj]s?(x)"
-  // ],
+    // The glob patterns Jest uses to detect test files
+    // testMatch: [
+    //   "**/__tests__/**/*.[jt]s?(x)",
+    //   "**/?(*.)+(spec|test).[tj]s?(x)"
+    // ],
 
-  // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
-  // testPathIgnorePatterns: [
-  //   "\\\\node_modules\\\\"
-  // ],
+    // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
+    // testPathIgnorePatterns: [
+    //   "\\\\node_modules\\\\"
+    // ],
 
-  // The regexp pattern or array of patterns that Jest uses to detect test files
-  // testRegex: [],
+    // The regexp pattern or array of patterns that Jest uses to detect test files
+    // testRegex: [],
 
-  // This option allows the use of a custom results processor
-  // testResultsProcessor: null,
+    // This option allows the use of a custom results processor
+    // testResultsProcessor: null,
 
-  // This option allows use of a custom test runner
-  // testRunner: "jasmine2",
+    // This option allows use of a custom test runner
+    // testRunner: "jasmine2",
 
-  // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
-  // testURL: "http://localhost",
+    // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
+    // testURL: "http://localhost",
 
-  // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
-  // timers: "real",
+    // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
+    // timers: "real",
 
-  // A map from regular expressions to paths to transformers
-  // transform: null,
+    // A map from regular expressions to paths to transformers
+    // transform: null,
 
-  // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
-  // transformIgnorePatterns: [
-  //   "\\\\node_modules\\\\"
-  // ],
+    // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
+    // transformIgnorePatterns: [
+    //   "\\\\node_modules\\\\"
+    // ],
 
-  // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
-  // unmockedModulePathPatterns: undefined,
+    // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
+    // unmockedModulePathPatterns: undefined,
 
-  // Indicates whether each individual test should be reported during the run
-  // verbose: null,
+    // Indicates whether each individual test should be reported during the run
+    // verbose: null,
 
-  // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
-  // watchPathIgnorePatterns: [],
+    // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
+    // watchPathIgnorePatterns: [],
 
-  // Whether to use watchman for file crawling
-  // watchman: true,
-};
+    // Whether to use watchman for file crawling
+    // watchman: true,
+}
diff --git a/package-lock.json b/package-lock.json
index 6a064621..5a36f0b2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,17 +13,17 @@
       }
     },
     "@babel/core": {
-      "version": "7.7.2",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
-      "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.7.tgz",
+      "integrity": "sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==",
       "requires": {
         "@babel/code-frame": "^7.5.5",
-        "@babel/generator": "^7.7.2",
-        "@babel/helpers": "^7.7.0",
-        "@babel/parser": "^7.7.2",
-        "@babel/template": "^7.7.0",
-        "@babel/traverse": "^7.7.2",
-        "@babel/types": "^7.7.2",
+        "@babel/generator": "^7.7.7",
+        "@babel/helpers": "^7.7.4",
+        "@babel/parser": "^7.7.7",
+        "@babel/template": "^7.7.4",
+        "@babel/traverse": "^7.7.4",
+        "@babel/types": "^7.7.4",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "json5": "^2.1.0",
@@ -31,6 +31,86 @@
         "resolve": "^1.3.2",
         "semver": "^5.4.1",
         "source-map": "^0.5.0"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/generator": {
@@ -48,27 +128,120 @@
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz",
       "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==",
+      "dev": true,
       "requires": {
         "@babel/types": "^7.7.0"
       }
     },
     "@babel/helper-builder-binary-assignment-operator-visitor": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz",
-      "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz",
+      "integrity": "sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==",
       "requires": {
-        "@babel/helper-explode-assignable-expression": "^7.7.0",
-        "@babel/types": "^7.7.0"
+        "@babel/helper-explode-assignable-expression": "^7.7.4",
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-call-delegate": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz",
-      "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz",
+      "integrity": "sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==",
       "requires": {
-        "@babel/helper-hoist-variables": "^7.7.0",
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0"
+        "@babel/helper-hoist-variables": "^7.7.4",
+        "@babel/traverse": "^7.7.4",
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-create-class-features-plugin": {
@@ -85,31 +258,156 @@
       }
     },
     "@babel/helper-create-regexp-features-plugin": {
-      "version": "7.7.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz",
-      "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz",
+      "integrity": "sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==",
       "requires": {
         "@babel/helper-regex": "^7.4.4",
         "regexpu-core": "^4.6.0"
       }
     },
     "@babel/helper-define-map": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz",
-      "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz",
+      "integrity": "sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==",
       "requires": {
-        "@babel/helper-function-name": "^7.7.0",
-        "@babel/types": "^7.7.0",
+        "@babel/helper-function-name": "^7.7.4",
+        "@babel/types": "^7.7.4",
         "lodash": "^4.17.13"
+      },
+      "dependencies": {
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-explode-assignable-expression": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz",
-      "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz",
+      "integrity": "sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==",
       "requires": {
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0"
+        "@babel/traverse": "^7.7.4",
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-function-name": {
@@ -131,11 +429,23 @@
       }
     },
     "@babel/helper-hoist-variables": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz",
-      "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz",
+      "integrity": "sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==",
       "requires": {
-        "@babel/types": "^7.7.0"
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-member-expression-to-functions": {
@@ -150,21 +460,65 @@
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz",
       "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==",
+      "dev": true,
       "requires": {
         "@babel/types": "^7.7.0"
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz",
-      "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==",
-      "requires": {
-        "@babel/helper-module-imports": "^7.7.0",
-        "@babel/helper-simple-access": "^7.7.0",
-        "@babel/helper-split-export-declaration": "^7.7.0",
-        "@babel/template": "^7.7.0",
-        "@babel/types": "^7.7.0",
+      "version": "7.7.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz",
+      "integrity": "sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw==",
+      "requires": {
+        "@babel/helper-module-imports": "^7.7.4",
+        "@babel/helper-simple-access": "^7.7.4",
+        "@babel/helper-split-export-declaration": "^7.7.4",
+        "@babel/template": "^7.7.4",
+        "@babel/types": "^7.7.4",
         "lodash": "^4.17.13"
+      },
+      "dependencies": {
+        "@babel/helper-module-imports": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz",
+          "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-optimise-call-expression": {
@@ -192,6 +546,7 @@
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz",
       "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==",
+      "dev": true,
       "requires": {
         "@babel/helper-annotate-as-pure": "^7.7.0",
         "@babel/helper-wrap-function": "^7.7.0",
@@ -212,12 +567,39 @@
       }
     },
     "@babel/helper-simple-access": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz",
-      "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz",
+      "integrity": "sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==",
       "requires": {
-        "@babel/template": "^7.7.0",
-        "@babel/types": "^7.7.0"
+        "@babel/template": "^7.7.4",
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/helper-split-export-declaration": {
@@ -232,6 +614,7 @@
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz",
       "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==",
+      "dev": true,
       "requires": {
         "@babel/helper-function-name": "^7.7.0",
         "@babel/template": "^7.7.0",
@@ -240,13 +623,93 @@
       }
     },
     "@babel/helpers": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz",
-      "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz",
+      "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==",
       "requires": {
-        "@babel/template": "^7.7.0",
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0"
+        "@babel/template": "^7.7.4",
+        "@babel/traverse": "^7.7.4",
+        "@babel/types": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/highlight": {
@@ -265,13 +728,124 @@
       "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A=="
     },
     "@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz",
-      "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz",
+      "integrity": "sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/helper-remap-async-to-generator": "^7.7.0",
-        "@babel/plugin-syntax-async-generators": "^7.2.0"
+        "@babel/helper-remap-async-to-generator": "^7.7.4",
+        "@babel/plugin-syntax-async-generators": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz",
+          "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-remap-async-to-generator": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz",
+          "integrity": "sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==",
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.7.4",
+            "@babel/helper-wrap-function": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-wrap-function": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz",
+          "integrity": "sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==",
+          "requires": {
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-proposal-class-properties": {
@@ -284,70 +858,80 @@
       }
     },
     "@babel/plugin-proposal-dynamic-import": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz",
-      "integrity": "sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz",
+      "integrity": "sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/plugin-syntax-dynamic-import": "^7.2.0"
+        "@babel/plugin-syntax-dynamic-import": "^7.7.4"
       }
     },
     "@babel/plugin-proposal-json-strings": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
-      "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz",
+      "integrity": "sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/plugin-syntax-json-strings": "^7.2.0"
+        "@babel/plugin-syntax-json-strings": "^7.7.4"
       }
     },
     "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz",
-      "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz",
+      "integrity": "sha512-3qp9I8lelgzNedI3hrhkvhaEYree6+WHnyA/q4Dza9z7iEIs1eyhWyJnetk3jJ69RT0AT4G0UhEGwyGFJ7GUuQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+        "@babel/plugin-syntax-object-rest-spread": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/plugin-syntax-object-rest-spread": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz",
+          "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==",
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-proposal-optional-catch-binding": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
-      "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz",
+      "integrity": "sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+        "@babel/plugin-syntax-optional-catch-binding": "^7.7.4"
       }
     },
     "@babel/plugin-proposal-unicode-property-regex": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz",
-      "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.7.tgz",
+      "integrity": "sha512-80PbkKyORBUVm1fbTLrHpYdJxMThzM1UqFGh0ALEhO9TYbG86Ah9zQYAB/84axz2vcxefDLdZwWwZNlYARlu9w==",
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.7.0",
+        "@babel/helper-create-regexp-features-plugin": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-syntax-async-generators": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
-      "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz",
+      "integrity": "sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-syntax-dynamic-import": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz",
-      "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz",
+      "integrity": "sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-syntax-json-strings": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
-      "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz",
+      "integrity": "sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
@@ -356,30 +940,31 @@
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
       "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+      "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-syntax-optional-catch-binding": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
-      "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz",
+      "integrity": "sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-syntax-top-level-await": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz",
-      "integrity": "sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz",
+      "integrity": "sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-arrow-functions": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
-      "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz",
+      "integrity": "sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
@@ -388,6 +973,7 @@
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz",
       "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==",
+      "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.7.0",
         "@babel/helper-plugin-utils": "^7.0.0",
@@ -395,318 +981,762 @@
       }
     },
     "@babel/plugin-transform-block-scoped-functions": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
-      "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz",
+      "integrity": "sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-block-scoping": {
-      "version": "7.6.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz",
-      "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz",
+      "integrity": "sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
         "lodash": "^4.17.13"
       }
     },
     "@babel/plugin-transform-classes": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz",
-      "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==",
-      "requires": {
-        "@babel/helper-annotate-as-pure": "^7.7.0",
-        "@babel/helper-define-map": "^7.7.0",
-        "@babel/helper-function-name": "^7.7.0",
-        "@babel/helper-optimise-call-expression": "^7.7.0",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz",
+      "integrity": "sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==",
+      "requires": {
+        "@babel/helper-annotate-as-pure": "^7.7.4",
+        "@babel/helper-define-map": "^7.7.4",
+        "@babel/helper-function-name": "^7.7.4",
+        "@babel/helper-optimise-call-expression": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/helper-replace-supers": "^7.7.0",
-        "@babel/helper-split-export-declaration": "^7.7.0",
+        "@babel/helper-replace-supers": "^7.7.4",
+        "@babel/helper-split-export-declaration": "^7.7.4",
         "globals": "^11.1.0"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz",
+          "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-member-expression-to-functions": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz",
+          "integrity": "sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-optimise-call-expression": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz",
+          "integrity": "sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-replace-supers": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz",
+          "integrity": "sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==",
+          "requires": {
+            "@babel/helper-member-expression-to-functions": "^7.7.4",
+            "@babel/helper-optimise-call-expression": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-transform-computed-properties": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
-      "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz",
+      "integrity": "sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-destructuring": {
-      "version": "7.6.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz",
-      "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz",
+      "integrity": "sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-dotall-regex": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz",
-      "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.7.tgz",
+      "integrity": "sha512-b4in+YlTeE/QmTgrllnb3bHA0HntYvjz8O3Mcbx75UBPJA2xhb5A8nle498VhxSXJHQefjtQxpnLPehDJ4TRlg==",
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.7.0",
+        "@babel/helper-create-regexp-features-plugin": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-duplicate-keys": {
-      "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz",
-      "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz",
+      "integrity": "sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-exponentiation-operator": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
-      "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz",
+      "integrity": "sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==",
       "requires": {
-        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
+        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-for-of": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
-      "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz",
+      "integrity": "sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-function-name": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz",
-      "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz",
+      "integrity": "sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==",
       "requires": {
-        "@babel/helper-function-name": "^7.7.0",
+        "@babel/helper-function-name": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
+      },
+      "dependencies": {
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-transform-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
-      "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz",
+      "integrity": "sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-member-expression-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
-      "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz",
+      "integrity": "sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-modules-amd": {
-      "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz",
-      "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==",
+      "version": "7.7.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz",
+      "integrity": "sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ==",
       "requires": {
-        "@babel/helper-module-transforms": "^7.1.0",
+        "@babel/helper-module-transforms": "^7.7.5",
         "@babel/helper-plugin-utils": "^7.0.0",
         "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-commonjs": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz",
-      "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==",
+      "version": "7.7.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz",
+      "integrity": "sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q==",
       "requires": {
-        "@babel/helper-module-transforms": "^7.7.0",
+        "@babel/helper-module-transforms": "^7.7.5",
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/helper-simple-access": "^7.7.0",
+        "@babel/helper-simple-access": "^7.7.4",
         "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz",
-      "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz",
+      "integrity": "sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw==",
       "requires": {
-        "@babel/helper-hoist-variables": "^7.7.0",
+        "@babel/helper-hoist-variables": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0",
         "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-umd": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz",
-      "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz",
+      "integrity": "sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw==",
       "requires": {
-        "@babel/helper-module-transforms": "^7.7.0",
+        "@babel/helper-module-transforms": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-named-capturing-groups-regex": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz",
-      "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz",
+      "integrity": "sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw==",
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.7.0"
+        "@babel/helper-create-regexp-features-plugin": "^7.7.4"
       }
     },
     "@babel/plugin-transform-new-target": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz",
-      "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz",
+      "integrity": "sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-object-super": {
-      "version": "7.5.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
-      "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz",
+      "integrity": "sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/helper-replace-supers": "^7.5.5"
+        "@babel/helper-replace-supers": "^7.7.4"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-member-expression-to-functions": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz",
+          "integrity": "sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-optimise-call-expression": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz",
+          "integrity": "sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-replace-supers": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz",
+          "integrity": "sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==",
+          "requires": {
+            "@babel/helper-member-expression-to-functions": "^7.7.4",
+            "@babel/helper-optimise-call-expression": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-transform-parameters": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
-      "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz",
+      "integrity": "sha512-OhGSrf9ZBrr1fw84oFXj5hgi8Nmg+E2w5L7NhnG0lPvpDtqd7dbyilM2/vR8CKbJ907RyxPh2kj6sBCSSfI9Ew==",
       "requires": {
-        "@babel/helper-call-delegate": "^7.4.4",
-        "@babel/helper-get-function-arity": "^7.0.0",
+        "@babel/helper-call-delegate": "^7.7.4",
+        "@babel/helper-get-function-arity": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
+      },
+      "dependencies": {
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-transform-property-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
-      "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz",
+      "integrity": "sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-regenerator": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz",
-      "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==",
+      "version": "7.7.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz",
+      "integrity": "sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw==",
       "requires": {
         "regenerator-transform": "^0.14.0"
       }
     },
     "@babel/plugin-transform-reserved-words": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz",
-      "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz",
+      "integrity": "sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-shorthand-properties": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
-      "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz",
+      "integrity": "sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-spread": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz",
-      "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz",
+      "integrity": "sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-sticky-regex": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
-      "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz",
+      "integrity": "sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
         "@babel/helper-regex": "^7.0.0"
       }
     },
     "@babel/plugin-transform-template-literals": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
-      "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz",
+      "integrity": "sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==",
       "requires": {
-        "@babel/helper-annotate-as-pure": "^7.0.0",
+        "@babel/helper-annotate-as-pure": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
+      },
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz",
+          "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/plugin-transform-typeof-symbol": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
-      "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz",
+      "integrity": "sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/plugin-transform-unicode-regex": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz",
-      "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz",
+      "integrity": "sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==",
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.7.0",
+        "@babel/helper-create-regexp-features-plugin": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0"
       }
     },
     "@babel/preset-env": {
-      "version": "7.7.1",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.1.tgz",
-      "integrity": "sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA==",
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.7.tgz",
+      "integrity": "sha512-pCu0hrSSDVI7kCVUOdcMNQEbOPJ52E+LrQ14sN8uL2ALfSqePZQlKrOy+tM4uhEdYlCHi4imr8Zz2cZe9oSdIg==",
       "requires": {
-        "@babel/helper-module-imports": "^7.7.0",
+        "@babel/helper-module-imports": "^7.7.4",
         "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/plugin-proposal-async-generator-functions": "^7.7.0",
-        "@babel/plugin-proposal-dynamic-import": "^7.7.0",
-        "@babel/plugin-proposal-json-strings": "^7.2.0",
-        "@babel/plugin-proposal-object-rest-spread": "^7.6.2",
-        "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
-        "@babel/plugin-proposal-unicode-property-regex": "^7.7.0",
-        "@babel/plugin-syntax-async-generators": "^7.2.0",
-        "@babel/plugin-syntax-dynamic-import": "^7.2.0",
-        "@babel/plugin-syntax-json-strings": "^7.2.0",
-        "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
-        "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
-        "@babel/plugin-syntax-top-level-await": "^7.7.0",
-        "@babel/plugin-transform-arrow-functions": "^7.2.0",
-        "@babel/plugin-transform-async-to-generator": "^7.7.0",
-        "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
-        "@babel/plugin-transform-block-scoping": "^7.6.3",
-        "@babel/plugin-transform-classes": "^7.7.0",
-        "@babel/plugin-transform-computed-properties": "^7.2.0",
-        "@babel/plugin-transform-destructuring": "^7.6.0",
-        "@babel/plugin-transform-dotall-regex": "^7.7.0",
-        "@babel/plugin-transform-duplicate-keys": "^7.5.0",
-        "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
-        "@babel/plugin-transform-for-of": "^7.4.4",
-        "@babel/plugin-transform-function-name": "^7.7.0",
-        "@babel/plugin-transform-literals": "^7.2.0",
-        "@babel/plugin-transform-member-expression-literals": "^7.2.0",
-        "@babel/plugin-transform-modules-amd": "^7.5.0",
-        "@babel/plugin-transform-modules-commonjs": "^7.7.0",
-        "@babel/plugin-transform-modules-systemjs": "^7.7.0",
-        "@babel/plugin-transform-modules-umd": "^7.7.0",
-        "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.0",
-        "@babel/plugin-transform-new-target": "^7.4.4",
-        "@babel/plugin-transform-object-super": "^7.5.5",
-        "@babel/plugin-transform-parameters": "^7.4.4",
-        "@babel/plugin-transform-property-literals": "^7.2.0",
-        "@babel/plugin-transform-regenerator": "^7.7.0",
-        "@babel/plugin-transform-reserved-words": "^7.2.0",
-        "@babel/plugin-transform-shorthand-properties": "^7.2.0",
-        "@babel/plugin-transform-spread": "^7.6.2",
-        "@babel/plugin-transform-sticky-regex": "^7.2.0",
-        "@babel/plugin-transform-template-literals": "^7.4.4",
-        "@babel/plugin-transform-typeof-symbol": "^7.2.0",
-        "@babel/plugin-transform-unicode-regex": "^7.7.0",
-        "@babel/types": "^7.7.1",
+        "@babel/plugin-proposal-async-generator-functions": "^7.7.4",
+        "@babel/plugin-proposal-dynamic-import": "^7.7.4",
+        "@babel/plugin-proposal-json-strings": "^7.7.4",
+        "@babel/plugin-proposal-object-rest-spread": "^7.7.7",
+        "@babel/plugin-proposal-optional-catch-binding": "^7.7.4",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.7.7",
+        "@babel/plugin-syntax-async-generators": "^7.7.4",
+        "@babel/plugin-syntax-dynamic-import": "^7.7.4",
+        "@babel/plugin-syntax-json-strings": "^7.7.4",
+        "@babel/plugin-syntax-object-rest-spread": "^7.7.4",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.7.4",
+        "@babel/plugin-syntax-top-level-await": "^7.7.4",
+        "@babel/plugin-transform-arrow-functions": "^7.7.4",
+        "@babel/plugin-transform-async-to-generator": "^7.7.4",
+        "@babel/plugin-transform-block-scoped-functions": "^7.7.4",
+        "@babel/plugin-transform-block-scoping": "^7.7.4",
+        "@babel/plugin-transform-classes": "^7.7.4",
+        "@babel/plugin-transform-computed-properties": "^7.7.4",
+        "@babel/plugin-transform-destructuring": "^7.7.4",
+        "@babel/plugin-transform-dotall-regex": "^7.7.7",
+        "@babel/plugin-transform-duplicate-keys": "^7.7.4",
+        "@babel/plugin-transform-exponentiation-operator": "^7.7.4",
+        "@babel/plugin-transform-for-of": "^7.7.4",
+        "@babel/plugin-transform-function-name": "^7.7.4",
+        "@babel/plugin-transform-literals": "^7.7.4",
+        "@babel/plugin-transform-member-expression-literals": "^7.7.4",
+        "@babel/plugin-transform-modules-amd": "^7.7.5",
+        "@babel/plugin-transform-modules-commonjs": "^7.7.5",
+        "@babel/plugin-transform-modules-systemjs": "^7.7.4",
+        "@babel/plugin-transform-modules-umd": "^7.7.4",
+        "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.4",
+        "@babel/plugin-transform-new-target": "^7.7.4",
+        "@babel/plugin-transform-object-super": "^7.7.4",
+        "@babel/plugin-transform-parameters": "^7.7.7",
+        "@babel/plugin-transform-property-literals": "^7.7.4",
+        "@babel/plugin-transform-regenerator": "^7.7.5",
+        "@babel/plugin-transform-reserved-words": "^7.7.4",
+        "@babel/plugin-transform-shorthand-properties": "^7.7.4",
+        "@babel/plugin-transform-spread": "^7.7.4",
+        "@babel/plugin-transform-sticky-regex": "^7.7.4",
+        "@babel/plugin-transform-template-literals": "^7.7.4",
+        "@babel/plugin-transform-typeof-symbol": "^7.7.4",
+        "@babel/plugin-transform-unicode-regex": "^7.7.4",
+        "@babel/types": "^7.7.4",
         "browserslist": "^4.6.0",
-        "core-js-compat": "^3.1.1",
+        "core-js-compat": "^3.6.0",
         "invariant": "^2.2.2",
         "js-levenshtein": "^1.1.3",
         "semver": "^5.5.0"
+      },
+      "dependencies": {
+        "@babel/generator": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+          "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+          "requires": {
+            "@babel/types": "^7.7.4",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.13",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz",
+          "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+          "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+          "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-module-imports": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz",
+          "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-remap-async-to-generator": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz",
+          "integrity": "sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==",
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.7.4",
+            "@babel/helper-wrap-function": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+          "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+          "requires": {
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/helper-wrap-function": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz",
+          "integrity": "sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==",
+          "requires": {
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/template": "^7.7.4",
+            "@babel/traverse": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+          "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw=="
+        },
+        "@babel/plugin-syntax-object-rest-spread": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz",
+          "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==",
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.0.0"
+          }
+        },
+        "@babel/plugin-transform-async-to-generator": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz",
+          "integrity": "sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==",
+          "requires": {
+            "@babel/helper-module-imports": "^7.7.4",
+            "@babel/helper-plugin-utils": "^7.0.0",
+            "@babel/helper-remap-async-to-generator": "^7.7.4"
+          }
+        },
+        "@babel/template": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+          "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+          "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+          "requires": {
+            "@babel/code-frame": "^7.5.5",
+            "@babel/generator": "^7.7.4",
+            "@babel/helper-function-name": "^7.7.4",
+            "@babel/helper-split-export-declaration": "^7.7.4",
+            "@babel/parser": "^7.7.4",
+            "@babel/types": "^7.7.4",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.13"
+          }
+        },
+        "@babel/types": {
+          "version": "7.7.4",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+          "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.13",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
       }
     },
     "@babel/template": {
@@ -2114,13 +3144,13 @@
       }
     },
     "browserslist": {
-      "version": "4.7.3",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.3.tgz",
-      "integrity": "sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==",
+      "version": "4.8.3",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.3.tgz",
+      "integrity": "sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==",
       "requires": {
-        "caniuse-lite": "^1.0.30001010",
-        "electron-to-chromium": "^1.3.306",
-        "node-releases": "^1.1.40"
+        "caniuse-lite": "^1.0.30001017",
+        "electron-to-chromium": "^1.3.322",
+        "node-releases": "^1.1.44"
       }
     },
     "bser": {
@@ -2212,9 +3242,9 @@
       "dev": true
     },
     "caniuse-lite": {
-      "version": "1.0.30001010",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001010.tgz",
-      "integrity": "sha512-RA5GH9YjFNea4ZQszdWgh2SC+dpLiRAg4VDQS2b5JRI45OxmbGrYocYHTa9x0bKMQUE7uvHkNPNffUr+pCxSGw=="
+      "version": "1.0.30001018",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001018.tgz",
+      "integrity": "sha512-GTHI7xdD2EX/U9UgNCEdekriT81N6ZwipsTGKAI1hrv3VEC96BvS5RVoc9Odlf9ftS92oxgflAGbYLi8UjIiVA=="
     },
     "capture-exit": {
       "version": "2.0.0",
@@ -2541,18 +3571,18 @@
       "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA=="
     },
     "core-js-compat": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.1.tgz",
-      "integrity": "sha512-YdeJI26gLc0CQJ9asLE5obEgBz2I0+CIgnoTbS2T0d5IPQw/OCgCIFR527RmpduxjrB3gSEHoGOCTq9sigOyfw==",
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.1.tgz",
+      "integrity": "sha512-2Tl1EuxZo94QS2VeH28Ebf5g3xbPZG/hj/N5HDDy4XMP/ImR0JIer/nggQRiMN91Q54JVkGbytf42wO29oXVHg==",
       "requires": {
-        "browserslist": "^4.7.2",
-        "semver": "^6.3.0"
+        "browserslist": "^4.8.2",
+        "semver": "7.0.0"
       },
       "dependencies": {
         "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+          "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
         }
       }
     },
@@ -2884,9 +3914,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.3.306",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.306.tgz",
-      "integrity": "sha512-frDqXvrIROoYvikSKTIKbHbzO6M3/qC6kCIt/1FOa9kALe++c4VAJnwjSFvf1tYLEUsP2n9XZ4XSCyqc3l7A/A=="
+      "version": "1.3.323",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.323.tgz",
+      "integrity": "sha512-c7pOUGnqNv6otzwcedViWOTGMEUG70PkhrTzVtc20Txh9nDC4s8zWvocJl7q+OpoC0ACXtxud8PX2y8zk/RZiw=="
     },
     "elliptic": {
       "version": "6.5.1",
@@ -6229,9 +7259,9 @@
       }
     },
     "node-releases": {
-      "version": "1.1.40",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.40.tgz",
-      "integrity": "sha512-r4LPcC5b/bS8BdtWH1fbeK88ib/wg9aqmg6/s3ngNLn2Ewkn/8J6Iw3P9RTlfIAdSdvYvQl2thCY5Y+qTAQ2iQ==",
+      "version": "1.1.44",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.44.tgz",
+      "integrity": "sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw==",
       "requires": {
         "semver": "^6.3.0"
       },
@@ -7107,9 +8137,9 @@
       "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg=="
     },
     "regjsparser": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
-      "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz",
+      "integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==",
       "requires": {
         "jsesc": "~0.5.0"
       },

From 101e44aff9d787bc062d9c4804ac06e7dbe9c88f Mon Sep 17 00:00:00 2001
From: Chris Watson 
Date: Sat, 4 Jan 2020 17:53:22 -0700
Subject: [PATCH 3/5] Add HTML spec

---
 __tests__/extensions/HTML.spec.js | 96 +++++++++++++++++++++++++++++++
 gramjs/extensions/HTML.js         |  8 ++-
 2 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 __tests__/extensions/HTML.spec.js

diff --git a/__tests__/extensions/HTML.spec.js b/__tests__/extensions/HTML.spec.js
new file mode 100644
index 00000000..ff7465e1
--- /dev/null
+++ b/__tests__/extensions/HTML.spec.js
@@ -0,0 +1,96 @@
+const { HTMLParser } = require('../../gramjs/extensions/HTML')
+const types = require('../../gramjs/tl/types')
+
+describe('HTMLParser', () => {
+    test('it should construct a new HTMLParser', () => {
+        const parser = new HTMLParser('Hello world')
+        expect(parser.text).toEqual('')
+        expect(parser.entities).toEqual([])
+    })
+
+    describe('.parse', () => {
+        test('it should parse bold entities', () => {
+            const parser = new HTMLParser('Hello world')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityBold)
+        })
+
+        test('it should parse italic entities', () => {
+            const parser = new HTMLParser('Hello world')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityItalic)
+        })
+
+        test('it should parse code entities', () => {
+            const parser = new HTMLParser('Hello world')
+            const [text, entities] = parser.parse()
+            expect(text).toEqual('Hello world')
+            expect(entities.length).toEqual(1)
+            expect(entities[0]).toBeInstanceOf(types.MessageEntityCode)
+        })
+
+        test('it should parse pre entities', () => {
+            const parser = new HTMLParser('Hello 
world
') + const [text, entities] = parser.parse() + expect(text).toEqual('Hello world') + expect(entities.length).toEqual(1) + expect(entities[0]).toBeInstanceOf(types.MessageEntityPre) + }) + + test('it should parse strike entities', () => { + const parser = new HTMLParser('Hello world') + const [text, entities] = parser.parse() + expect(text).toEqual('Hello world') + expect(entities.length).toEqual(1) + expect(entities[0]).toBeInstanceOf(types.MessageEntityStrike) + }) + + test('it should parse link entities', () => { + const parser = new HTMLParser('Hello world') + const [text, entities] = parser.parse() + expect(text).toEqual('Hello world') + expect(entities.length).toEqual(1) + expect(entities[0]).toBeInstanceOf(types.MessageEntityTextUrl) + expect(entities[0].url).toEqual('https://hello.world') + }) + + test('it should parse nested entities', () => { + const parser = new HTMLParser('Hello world') + const [text, entities] = parser.parse() + expect(text).toEqual('Hello world') + expect(entities.length).toEqual(2) + expect(entities[0]).toBeInstanceOf(types.MessageEntityItalic) + expect(entities[1]).toBeInstanceOf(types.MessageEntityBold) + }) + + test('it should parse multiple entities', () => { + const parser = new HTMLParser('Hello world') + const [text, entities] = parser.parse() + expect(text).toEqual('Hello world') + expect(entities.length).toEqual(2) + expect(entities[0]).toBeInstanceOf(types.MessageEntityItalic) + expect(entities[1]).toBeInstanceOf(types.MessageEntityBold) + }) + }) + + describe('.unparse', () => { + test('it should create a markdown string from raw text and entities', () => { + const unparsed = 'hello hello hello hello
hello
hello' + const strippedText = 'hello hello hello hello hello hello' + const rawEntities = [ + new types.MessageEntityBold({ offset: 0, length: 5 }), + new types.MessageEntityItalic({ offset: 6, length: 5 }), + new types.MessageEntityStrike({ offset: 12, length: 5 }), + new types.MessageEntityCode({ offset: 18, length: 5 }), + new types.MessageEntityPre({ offset: 24, length: 5 }), + new types.MessageEntityTextUrl({ offset: 30, length: 5, url: 'https://hello.world' }), + ] + const text = HTMLParser.unparse(strippedText, rawEntities) + expect(text).toEqual(unparsed) + }) + }) +}) diff --git a/gramjs/extensions/HTML.js b/gramjs/extensions/HTML.js index b841a698..db86a814 100644 --- a/gramjs/extensions/HTML.js +++ b/gramjs/extensions/HTML.js @@ -47,9 +47,13 @@ class HTMLParser extends Scanner { .map((a) => a.length === 1 ? a.concat([true]) : a) // Remove quotes if they exist .map((a) => { - const txt = a[0].replace(/^('|")|('|")$/, '') - return [txt, a[1]] + const attr = a[1].replace(/^('|")|('|")$/g, '') + return [a[0], attr] }) + .reduce((p, c) => { + p[c[0]] = c[1] + return p + }, {}) this.handleStartTag(tag, attrs) } From 5b17bd83709fa4c14a0e828ee5a004a8ba84ce3f Mon Sep 17 00:00:00 2001 From: Chris Watson Date: Sat, 4 Jan 2020 18:09:00 -0700 Subject: [PATCH 4/5] Add nested unparse test case --- __tests__/extensions/HTML.spec.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/__tests__/extensions/HTML.spec.js b/__tests__/extensions/HTML.spec.js index ff7465e1..b23c6414 100644 --- a/__tests__/extensions/HTML.spec.js +++ b/__tests__/extensions/HTML.spec.js @@ -92,5 +92,16 @@ describe('HTMLParser', () => { const text = HTMLParser.unparse(strippedText, rawEntities) expect(text).toEqual(unparsed) }) + + test('it should unparse nested entities', () => { + const unparsed = 'Hello world' + const strippedText = 'Hello world' + const rawEntities = [ + new types.MessageEntityBold({ offset: 0, length: 11 }), + new types.MessageEntityItalic({ offset: 0, length: 11 }), + ] + const text = HTMLParser.unparse(strippedText, rawEntities) + expect(text).toEqual(unparsed) + }) }) }) From d637087747c9079bae1c5329def6de1ec05f523b Mon Sep 17 00:00:00 2001 From: Chris Watson Date: Sat, 4 Jan 2020 18:10:10 -0700 Subject: [PATCH 5/5] Remove dangling log statement --- gramjs/extensions/Markdown.js | 1 - 1 file changed, 1 deletion(-) diff --git a/gramjs/extensions/Markdown.js b/gramjs/extensions/Markdown.js index 24eb0b36..927ff662 100644 --- a/gramjs/extensions/Markdown.js +++ b/gramjs/extensions/Markdown.js @@ -75,7 +75,6 @@ class MarkdownParser extends Scanner { let url = null if (entity instanceof MessageEntityTextUrl) { url = entity.url - console.log(url) } else if (entity instanceof MessageEntityMentionName) { url = `tg://user?id=${entity.userId}` }