From 25f5cca8a9708721fedb0974624b36ea239323fd Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:35:15 -0700
Subject: [PATCH 01/86] Remove unused jenkins.sh

---
 jenkins.sh | 39 ---------------------------------------
 1 file changed, 39 deletions(-)
 delete mode 100755 jenkins.sh

diff --git a/jenkins.sh b/jenkins.sh
deleted file mode 100755
index 70bc12e42d..0000000000
--- a/jenkins.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export NVM_DIR="$HOME/.nvm"
-[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
-nvm use 10
-
-set -x
-
-scripts/fetchdep.sh matrix-org matrix-js-sdk
-
-pushd matrix-js-sdk
-yarn link
-yarn install
-popd
-
-yarn link matrix-js-sdk
-
-# install the other dependencies
-yarn install
-
-# run the mocha tests
-yarn test --no-colors
-
-# run eslint
-yarn lintall -f checkstyle -o eslint.xml || true
-
-# re-run the linter, excluding any files known to have errors or warnings.
-yarn lintwithexclusions
-
-# lint styles
-yarn stylelint
-
-# delete the old tarball, if it exists
-rm -f matrix-react-sdk-*.tgz
-
-# build our tarball
-yarn pack

From c02beb9ba30aebb81c294783197b06e9bb651708 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:35:28 -0700
Subject: [PATCH 02/86] Copy typescript configs from js-sdk

---
 tsconfig.json | 19 ++++++++++++++
 tslint.json   | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 tsconfig.json
 create mode 100644 tslint.json

diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000000..ec1531e429
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,19 @@
+{
+  "compilerOptions": {
+    "experimentalDecorators": true,
+    "emitDecoratorMetadata": true,
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "target": "es2016",
+    "noImplicitAny": false,
+    "sourceMap": false,
+    "outDir": "./lib",
+    "declaration": true,
+    "types": [
+      "node"
+    ]
+  },
+  "include": [
+    "./src/**/*.ts"
+  ]
+}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 0000000000..fc234117fc
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,72 @@
+{
+  "rules": {
+    "class-name": false,
+    "comment-format": [
+      true
+    ],
+    "curly": false,
+    "eofline": false,
+    "forin": false,
+    "indent": [
+      true,
+      "spaces"
+    ],
+    "label-position": true,
+    "max-line-length": false,
+    "member-access": false,
+    "member-ordering": [
+      true,
+      "static-after-instance",
+      "variables-before-functions"
+    ],
+    "no-arg": true,
+    "no-bitwise": false,
+    "no-console": false,
+    "no-construct": true,
+    "no-debugger": true,
+    "no-duplicate-variable": true,
+    "no-empty": false,
+    "no-eval": true,
+    "no-inferrable-types": true,
+    "no-shadowed-variable": true,
+    "no-string-literal": false,
+    "no-switch-case-fall-through": true,
+    "no-trailing-whitespace": true,
+    "no-unused-expression": true,
+    "no-use-before-declare": false,
+    "no-var-keyword": true,
+    "object-literal-sort-keys": false,
+    "one-line": [
+      true,
+      "check-open-brace",
+      "check-catch",
+      "check-else",
+      "check-whitespace"
+    ],
+    "quotemark": false,
+    "radix": true,
+    "semicolon": [
+      "always"
+    ],
+    "triple-equals": [],
+    "typedef-whitespace": [
+      true,
+      {
+        "call-signature": "nospace",
+        "index-signature": "nospace",
+        "parameter": "nospace",
+        "property-declaration": "nospace",
+        "variable-declaration": "nospace"
+      }
+    ],
+    "variable-name": false,
+    "whitespace": [
+      true,
+      "check-branch",
+      "check-decl",
+      "check-operator",
+      "check-separator",
+      "check-type"
+    ]
+  }
+}

From 97af0403e5e0133ba4838c0190395bc4e27ccd31 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:37:14 -0700
Subject: [PATCH 03/86] Upgrade to babel@7 and support typescript

This breaks the tests
---
 .babelrc                 | 33 ++++++++++--------
 .buildkite/pipeline.yaml | 34 ++++++++++++++++---
 karma.conf.js            |  2 +-
 package.json             | 73 +++++++++++++++++++---------------------
 4 files changed, 85 insertions(+), 57 deletions(-)

diff --git a/.babelrc b/.babelrc
index abe7e1ef3f..3710e20a37 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,20 +1,25 @@
 {
+    "sourceMaps": "inline",
     "presets": [
-        "react",
-        "es2015",
-        "es2016"
+        ["@babel/preset-env", {
+            "targets": {
+                "browsers": [
+                    "last 2 versions"
+                ],
+                "node": 12
+            },
+            "modules": "commonjs"
+        }],
+        "@babel/preset-typescript",
+        "@babel/preset-flow",
+        "@babel/preset-react"
     ],
     "plugins": [
-        [
-            "transform-builtin-extend",
-            {
-                "globals": ["Error"]
-            }
-        ],
-        "transform-class-properties",
-        "transform-object-rest-spread",
-        "transform-runtime",
-        "add-module-exports",
-        "syntax-dynamic-import"
+        "@babel/plugin-proposal-numeric-separator",
+        "@babel/plugin-proposal-class-properties",
+        "@babel/plugin-proposal-object-rest-spread",
+        "@babel/plugin-transform-flow-comments",
+        "@babel/plugin-syntax-dynamic-import",
+        "@babel/plugin-transform-runtime"
     ]
 }
diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index be0d5e404c..8bbcdf78a4 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -1,13 +1,39 @@
 steps:
-  - label: ":eslint: Lint"
+  - label: ":eslint: JS Lint"
     command:
       - "echo '--- Install js-sdk'"
       - "./scripts/ci/install-deps.sh"
-      - "yarn lintwithexclusions"
-      - "yarn stylelint"
+      - "yarn lint:js"
     plugins:
       - docker#v3.0.1:
-          image: "node:10"
+          image: "node:12"
+
+  - label: ":eslint: TS Lint"
+    command:
+      - "echo '--- Install js-sdk'"
+      - "./scripts/ci/install-deps.sh"
+      - "yarn lint:ts"
+    plugins:
+      - docker#v3.0.1:
+          image: "node:12"
+
+  - label: ":eslint: Types Lint"
+    command:
+      - "echo '--- Install js-sdk'"
+      - "./scripts/ci/install-deps.sh"
+      - "yarn lint:types"
+    plugins:
+      - docker#v3.0.1:
+          image: "node:12"
+
+  - label: "🛠 Build"
+    command:
+      - "echo '--- Install js-sdk'"
+      - "./scripts/ci/install-deps.sh"
+      - "yarn build"
+    plugins:
+      - docker#v3.0.1:
+          image: "node:12"
 
   - label: ":chains: End-to-End Tests"
     agents:
diff --git a/karma.conf.js b/karma.conf.js
index d55be049bb..92e4e0e886 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -8,7 +8,7 @@ var fs = require('fs');
  * to build everything; however it's the easiest way to load our dependencies
  * from node_modules.
  *
- * If you run karma in multi-run mode (with `yarn test-multi`), it will watch
+ * If you run karma in multi-run mode (with `yarn test:multi`), it will watch
  * the tests for changes, and webpack will rebuild using a cache. This is much quicker
  * than a clean rebuild.
  */
diff --git a/package.json b/package.json
index 2f35ab7750..3b6e571d0c 100644
--- a/package.json
+++ b/package.json
@@ -8,10 +8,7 @@
     "url": "https://github.com/matrix-org/matrix-react-sdk"
   },
   "license": "Apache-2.0",
-  "main": "lib/index.js",
   "files": [
-    ".babelrc",
-    ".eslintrc.js",
     "CHANGELOG.md",
     "CONTRIBUTING.rst",
     "LICENSE",
@@ -19,14 +16,11 @@
     "code_style.md",
     "git-revision.txt",
     "header",
-    "jenkins.sh",
-    "karma.conf.js",
     "lib",
     "package.json",
-    "release.sh",
     "scripts",
+    "docs",
     "src",
-    "test",
     "res"
   ],
   "bin": {
@@ -34,32 +28,33 @@
     "matrix-gen-i18n": "scripts/gen-i18n.js",
     "matrix-prune-i18n": "scripts/prune-i18n.js"
   },
+  "main": "lib/index.js",
+  "typings": "lib/index.d.ts",
   "scripts": {
-    "reskindex": "node scripts/reskindex.js -h header",
-    "reskindex:watch": "node scripts/reskindex.js -h header -w",
-    "rethemendex": "res/css/rethemendex.sh",
     "i18n": "matrix-gen-i18n",
     "prunei18n": "matrix-prune-i18n",
     "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
-    "build": "yarn reskindex && yarn start:init",
-    "build:watch": "babel src -w --skip-initial-build -d lib --source-maps --copy-files",
     "emoji-data-strip": "node scripts/emoji-data-strip.js",
-    "start": "yarn start:init && yarn start:all",
-    "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn build:watch\" \"yarn reskindex:watch\"",
-    "start:init": "babel src -d lib --source-maps --copy-files",
-    "lint": "eslint src/",
-    "lintall": "eslint src/ test/",
-    "lintwithexclusions": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
-    "stylelint": "stylelint 'res/css/**/*.scss'",
+    "reskindex": "node scripts/reskindex.js -h header",
+    "reskindex:watch": "node scripts/reskindex.js -h header -w",
+    "rethemendex": "res/css/rethemendex.sh",
     "clean": "rimraf lib",
-    "prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt",
+    "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
+    "build:compile": "yarn reskindex && babel src -s -d lib --verbose --extensions \".ts,.js\"",
+    "build:types": "tsc --emitDeclarationOnly",
+    "start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all",
+    "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",
+    "start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
+    "lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
+    "lint:js": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
+    "lint:ts": "tslint --project ./tsconfig.json -t stylish",
+    "lint:types": "tsc --noEmit",
+    "lint:style": "stylelint 'res/css/**/*.scss'",
     "test": "karma start --single-run=true --browsers VectorChromeHeadless",
-    "test-multi": "karma start",
-    "e2etests": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
+    "test:multi": "karma start",
+    "test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
   },
   "dependencies": {
-    "babel-plugin-syntax-dynamic-import": "^6.18.0",
-    "babel-runtime": "^6.26.0",
     "blueimp-canvas-to-blob": "^3.5.0",
     "browser-encrypt-attachment": "^0.3.0",
     "browser-request": "^0.3.3",
@@ -115,20 +110,20 @@
     "zxcvbn": "^4.4.2"
   },
   "devDependencies": {
-    "babel-cli": "^6.26.0",
-    "babel-core": "^6.26.3",
-    "babel-eslint": "^10.0.1",
-    "babel-loader": "^7.1.5",
-    "babel-plugin-add-module-exports": "^0.2.1",
-    "babel-plugin-transform-builtin-extend": "^1.1.2",
-    "babel-plugin-transform-class-properties": "^6.24.1",
-    "babel-plugin-transform-object-rest-spread": "^6.26.0",
-    "babel-plugin-transform-runtime": "^6.23.0",
-    "babel-polyfill": "^6.26.0",
-    "babel-preset-es2015": "^6.24.1",
-    "babel-preset-es2016": "^6.24.1",
-    "babel-preset-es2017": "^6.24.1",
-    "babel-preset-react": "^6.24.1",
+    "@babel/cli": "^7.7.5",
+    "@babel/core": "^7.7.5",
+    "@babel/plugin-proposal-class-properties": "^7.7.4",
+    "@babel/plugin-proposal-numeric-separator": "^7.7.4",
+    "@babel/plugin-proposal-object-rest-spread": "^7.7.4",
+    "@babel/plugin-transform-flow-comments": "^7.7.4",
+    "@babel/plugin-transform-runtime": "^7.7.6",
+    "@babel/preset-env": "^7.7.6",
+    "@babel/preset-flow": "^7.7.4",
+    "@babel/preset-react": "^7.7.4",
+    "@babel/preset-typescript": "^7.7.4",
+    "@babel/register": "^7.7.4",
+    "@babel/runtime": "^7.7.6",
+    "babel-eslint": "^10.0.3",
     "chokidar": "^2.1.2",
     "concurrently": "^4.0.1",
     "eslint": "^5.12.0",
@@ -163,6 +158,8 @@
     "stylelint": "^9.10.1",
     "stylelint-config-standard": "^18.2.0",
     "stylelint-scss": "^3.9.0",
+    "tslint": "^5.20.1",
+    "typescript": "^3.7.3",
     "walk": "^2.3.9",
     "webpack": "^4.20.2",
     "webpack-cli": "^3.1.1"

From a5dadda63b30f30e74faf841de1b9bbb961fff33 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:37:32 -0700
Subject: [PATCH 04/86] Convert SdkConfig to TypeScript as a proof of concept

---
 src/ScalarAuthClient.js            |  2 +-
 src/{SdkConfig.js => SdkConfig.ts} | 32 ++++++++++++++++++++----------
 2 files changed, 23 insertions(+), 11 deletions(-)
 rename src/{SdkConfig.js => SdkConfig.ts} (70%)

diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js
index 92f0ff6340..c67f49ba26 100644
--- a/src/ScalarAuthClient.js
+++ b/src/ScalarAuthClient.js
@@ -20,10 +20,10 @@ import SettingsStore from "./settings/SettingsStore";
 import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
 const request = require('browser-request');
 
-const SdkConfig = require('./SdkConfig');
 const MatrixClientPeg = require('./MatrixClientPeg');
 
 import * as Matrix from 'matrix-js-sdk';
+import SdkConfig from "./SdkConfig";
 
 // The version of the integration manager API we're intending to work with
 const imApiVersion = "1.1";
diff --git a/src/SdkConfig.js b/src/SdkConfig.ts
similarity index 70%
rename from src/SdkConfig.js
rename to src/SdkConfig.ts
index eb18dad453..8177a6c5b8 100644
--- a/src/SdkConfig.js
+++ b/src/SdkConfig.ts
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +15,11 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export const DEFAULTS = {
+export interface ConfigOptions {
+    [key: string]: any;
+}
+
+export const DEFAULTS: ConfigOptions = {
     // URL to a page we show in an iframe to configure integrations
     integrations_ui_url: "https://scalar.vector.im/",
     // Base URL to the REST interface of the integrations server
@@ -23,30 +28,37 @@ export const DEFAULTS = {
     bug_report_endpoint_url: null,
 };
 
-class SdkConfig {
-    static get() {
-        return global.mxReactSdkConfig || {};
+export default class SdkConfig {
+    private static instance: ConfigOptions;
+
+    private static setInstance(i: ConfigOptions) {
+        SdkConfig.instance = i;
+
+        // For debugging purposes
+        (<any>window).mxReactSdkConfig = i;
     }
 
-    static put(cfg) {
+    static get() {
+        return SdkConfig.instance || {};
+    }
+
+    static put(cfg: ConfigOptions) {
         const defaultKeys = Object.keys(DEFAULTS);
         for (let i = 0; i < defaultKeys.length; ++i) {
             if (cfg[defaultKeys[i]] === undefined) {
                 cfg[defaultKeys[i]] = DEFAULTS[defaultKeys[i]];
             }
         }
-        global.mxReactSdkConfig = cfg;
+        SdkConfig.setInstance(cfg);
     }
 
     static unset() {
-        global.mxReactSdkConfig = undefined;
+        SdkConfig.setInstance({});
     }
 
-    static add(cfg) {
+    static add(cfg: ConfigOptions) {
         const liveConfig = SdkConfig.get();
         const newConfig = Object.assign({}, liveConfig, cfg);
         SdkConfig.put(newConfig);
     }
 }
-
-module.exports = SdkConfig;

From ff584d1644f4bb4e17149c0d05f9b2e1e32fd5ca Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:38:12 -0700
Subject: [PATCH 05/86] yarn.lock changes for upgrade

---
 yarn.lock | 2014 ++++++++++++++++++++++++-----------------------------
 1 file changed, 919 insertions(+), 1095 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 85deedbfec..6c05ab5933 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,22 @@
 # yarn lockfile v1
 
 
+"@babel/cli@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.5.tgz#25702cc65418efc06989af3727897b9f4c8690b6"
+  integrity sha512-y2YrMGXM3NUyu1Myg0pxg+Lx6g8XhEyvLHYNRwTBV6fDek3H7Io6b7N/LXscLs4HWn4HxMdy7f2rM1rTMp2mFg==
+  dependencies:
+    commander "^4.0.1"
+    convert-source-map "^1.1.0"
+    fs-readdir-recursive "^1.1.0"
+    glob "^7.0.0"
+    lodash "^4.17.13"
+    make-dir "^2.1.0"
+    slash "^2.0.0"
+    source-map "^0.5.0"
+  optionalDependencies:
+    chokidar "^2.1.8"
+
 "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
   version "7.5.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
@@ -29,6 +45,26 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
+"@babel/core@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e"
+  integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw==
+  dependencies:
+    "@babel/code-frame" "^7.5.5"
+    "@babel/generator" "^7.7.4"
+    "@babel/helpers" "^7.7.4"
+    "@babel/parser" "^7.7.5"
+    "@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"
+    lodash "^4.17.13"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
 "@babel/generator@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
@@ -39,6 +75,75 @@
     lodash "^4.17.13"
     source-map "^0.5.0"
 
+"@babel/helper-annotate-as-pure@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce"
+  integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f"
+  integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==
+  dependencies:
+    "@babel/helper-explode-assignable-expression" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-builder-react-jsx@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66"
+  integrity sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA==
+  dependencies:
+    "@babel/types" "^7.7.4"
+    esutils "^2.0.0"
+
+"@babel/helper-call-delegate@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801"
+  integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==
+  dependencies:
+    "@babel/helper-hoist-variables" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-create-class-features-plugin@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d"
+  integrity sha512-l+OnKACG4uiDHQ/aJT8dwpR+LhCJALxL0mJ6nzjB25e5IPwqV1VOsY7ah6UB1DG+VOXAIMtuC54rFJGiHkxjgA==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/helper-member-expression-to-functions" "^7.7.4"
+    "@babel/helper-optimise-call-expression" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-replace-supers" "^7.7.4"
+    "@babel/helper-split-export-declaration" "^7.7.4"
+
+"@babel/helper-create-regexp-features-plugin@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59"
+  integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==
+  dependencies:
+    "@babel/helper-regex" "^7.4.4"
+    regexpu-core "^4.6.0"
+
+"@babel/helper-define-map@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176"
+  integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    lodash "^4.17.13"
+
+"@babel/helper-explode-assignable-expression@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84"
+  integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==
+  dependencies:
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-function-name@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
@@ -55,6 +160,87 @@
   dependencies:
     "@babel/types" "^7.7.4"
 
+"@babel/helper-hoist-variables@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12"
+  integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-member-expression-to-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74"
+  integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-module-imports@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91"
+  integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835"
+  integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw==
+  dependencies:
+    "@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"
+
+"@babel/helper-optimise-call-expression@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2"
+  integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-plugin-utils@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
+  integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+
+"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
+  version "7.5.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
+  integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==
+  dependencies:
+    lodash "^4.17.13"
+
+"@babel/helper-remap-async-to-generator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234"
+  integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==
+  dependencies:
+    "@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-replace-supers@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2"
+  integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==
+  dependencies:
+    "@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-simple-access@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294"
+  integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==
+  dependencies:
+    "@babel/template" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-split-export-declaration@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
@@ -62,6 +248,16 @@
   dependencies:
     "@babel/types" "^7.7.4"
 
+"@babel/helper-wrap-function@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace"
+  integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/template" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helpers@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
@@ -85,6 +281,553 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb"
   integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==
 
+"@babel/parser@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
+  integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==
+
+"@babel/plugin-proposal-async-generator-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d"
+  integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-remap-async-to-generator" "^7.7.4"
+    "@babel/plugin-syntax-async-generators" "^7.7.4"
+
+"@babel/plugin-proposal-class-properties@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz#2f964f0cb18b948450362742e33e15211e77c2ba"
+  integrity sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw==
+  dependencies:
+    "@babel/helper-create-class-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-proposal-dynamic-import@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d"
+  integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-dynamic-import" "^7.7.4"
+
+"@babel/plugin-proposal-json-strings@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d"
+  integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-json-strings" "^7.7.4"
+
+"@babel/plugin-proposal-numeric-separator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.7.4.tgz#7819a17445f4197bb9575e5750ed349776da858a"
+  integrity sha512-CG605v7lLpVgVldSY6kxsN9ui1DxFOyepBfuX2AzU2TNriMAYApoU55mrGw9Jr4TlrTzPCG10CL8YXyi+E/iPw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-numeric-separator" "^7.7.4"
+
+"@babel/plugin-proposal-object-rest-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz#cc57849894a5c774214178c8ab64f6334ec8af71"
+  integrity sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-object-rest-spread" "^7.7.4"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379"
+  integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.7.4"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz#7c239ccaf09470dbe1d453d50057460e84517ebb"
+  integrity sha512-cHgqHgYvffluZk85dJ02vloErm3Y6xtH+2noOBOJ2kXOJH3aVCDnj5eR/lVNlTnYu4hndAPJD3rTFjW3qee0PA==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-async-generators@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889"
+  integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-dynamic-import@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec"
+  integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-flow@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b"
+  integrity sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-json-strings@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc"
+  integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-jsx@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec"
+  integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.7.4.tgz#39818f8042a09d4c6248d85d82555369da4da5c4"
+  integrity sha512-vmlUUBlLuFnbpaR+1kKIdo62xQEN+THWbtAHSEilo+0rHl2dKKCn6GLUVKpI848wL/T0ZPQgAy8asRJ9yYEjog==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-object-rest-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46"
+  integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6"
+  integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-top-level-await@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da"
+  integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-typescript@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz#5d037ffa10f3b25a16f32570ebbe7a8c2efa304b"
+  integrity sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-arrow-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12"
+  integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-async-to-generator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba"
+  integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-remap-async-to-generator" "^7.7.4"
+
+"@babel/plugin-transform-block-scoped-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b"
+  integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-block-scoping@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224"
+  integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    lodash "^4.17.13"
+
+"@babel/plugin-transform-classes@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec"
+  integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==
+  dependencies:
+    "@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.4"
+    "@babel/helper-split-export-declaration" "^7.7.4"
+    globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d"
+  integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-destructuring@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267"
+  integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-dotall-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.4.tgz#f7ccda61118c5b7a2599a72d5e3210884a021e96"
+  integrity sha512-mk0cH1zyMa/XHeb6LOTXTbG7uIJ8Rrjlzu91pUx/KS3JpcgaTDwMS8kM+ar8SLOvlL2Lofi4CGBAjCo3a2x+lw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-duplicate-keys@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91"
+  integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-exponentiation-operator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9"
+  integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==
+  dependencies:
+    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-flow-comments@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-comments/-/plugin-transform-flow-comments-7.7.4.tgz#663be88fc101b982975bdac4eefc15ba475b3368"
+  integrity sha512-e3nHGPo/wQcQMmNAHyqaM3Cl8dNKLognPi1RPmObnuVwyI6gHAQJtW6sg5HiNP4LBGRlPW8Npihm0/EzS/1Pzw==
+  dependencies:
+    "@babel/generator" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-flow" "^7.7.4"
+
+"@babel/plugin-transform-flow-strip-types@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz#cc73f85944782df1d77d80977bc097920a8bf31a"
+  integrity sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-flow" "^7.7.4"
+
+"@babel/plugin-transform-for-of@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc"
+  integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-function-name@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1"
+  integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e"
+  integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-member-expression-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a"
+  integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-amd@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c"
+  integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ==
+  dependencies:
+    "@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@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345"
+  integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.7.5"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-simple-access" "^7.7.4"
+    babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-systemjs@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30"
+  integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw==
+  dependencies:
+    "@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@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f"
+  integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220"
+  integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+
+"@babel/plugin-transform-new-target@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167"
+  integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-object-super@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262"
+  integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-replace-supers" "^7.7.4"
+
+"@babel/plugin-transform-parameters@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz#da4555c97f39b51ac089d31c7380f03bca4075ce"
+  integrity sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw==
+  dependencies:
+    "@babel/helper-call-delegate" "^7.7.4"
+    "@babel/helper-get-function-arity" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-property-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2"
+  integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-react-display-name@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.7.4.tgz#9f2b80b14ebc97eef4a9b29b612c58ed9c0d10dd"
+  integrity sha512-sBbIvqYkthai0X0vkD2xsAwluBp+LtNHH+/V4a5ydifmTtb8KOVOlrMIk/MYmIc4uTYDnjZUHQildYNo36SRJw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-react-jsx-self@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.7.4.tgz#81b8fbfd14b2215e8f1c2c3adfba266127b0231c"
+  integrity sha512-PWYjSfqrO273mc1pKCRTIJXyqfc9vWYBax88yIhQb+bpw3XChVC7VWS4VwRVs63wFHKxizvGSd00XEr+YB9Q2A==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-jsx" "^7.7.4"
+
+"@babel/plugin-transform-react-jsx-source@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.7.4.tgz#8994b1bf6014b133f5a46d3b7d1ee5f5e3e72c10"
+  integrity sha512-5ZU9FnPhqtHsOXxutRtXZAzoEJwDaP32QcobbMP1/qt7NYcsCNK8XgzJcJfoEr/ZnzVvUNInNjIW22Z6I8p9mg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-jsx" "^7.7.4"
+
+"@babel/plugin-transform-react-jsx@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.4.tgz#d91205717fae4e2f84d020cd3057ec02a10f11da"
+  integrity sha512-LixU4BS95ZTEAZdPaIuyg/k8FiiqN9laQ0dMHB4MlpydHY53uQdWCUrwjLr5o6ilS6fAgZey4Q14XBjl5tL6xw==
+  dependencies:
+    "@babel/helper-builder-react-jsx" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-jsx" "^7.7.4"
+
+"@babel/plugin-transform-regenerator@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9"
+  integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw==
+  dependencies:
+    regenerator-transform "^0.14.0"
+
+"@babel/plugin-transform-reserved-words@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb"
+  integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-runtime@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.6.tgz#4f2b548c88922fb98ec1c242afd4733ee3e12f61"
+  integrity sha512-tajQY+YmXR7JjTwRvwL4HePqoL3DYxpYXIHKVvrOIvJmeHe2y1w4tz5qz9ObUDC9m76rCzIMPyn4eERuwA4a4A==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    resolve "^1.8.1"
+    semver "^5.5.1"
+
+"@babel/plugin-transform-shorthand-properties@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e"
+  integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578"
+  integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-sticky-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c"
+  integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-regex" "^7.0.0"
+
+"@babel/plugin-transform-template-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604"
+  integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-typeof-symbol@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e"
+  integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-typescript@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz#2974fd05f4e85c695acaf497f432342de9fc0636"
+  integrity sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg==
+  dependencies:
+    "@babel/helper-create-class-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-typescript" "^7.7.4"
+
+"@babel/plugin-transform-unicode-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae"
+  integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/preset-env@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.6.tgz#39ac600427bbb94eec6b27953f1dfa1d64d457b2"
+  integrity sha512-k5hO17iF/Q7tR9Jv8PdNBZWYW6RofxhnxKjBMc0nG4JTaWvOTiPoO/RLFwAKcA4FpmuBFm6jkoqaRJLGi0zdaQ==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@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.4"
+    "@babel/plugin-proposal-optional-catch-binding" "^7.7.4"
+    "@babel/plugin-proposal-unicode-property-regex" "^7.7.4"
+    "@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.4"
+    "@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.4"
+    "@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.4.7"
+    invariant "^2.2.2"
+    js-levenshtein "^1.1.3"
+    semver "^5.5.0"
+
+"@babel/preset-flow@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.7.4.tgz#99c1349b6fd7132783196de181e6b32d0949427e"
+  integrity sha512-6LbUqcHD8BcRtXMOp5bc5nJeU8RlKh6q5U8TgZeCrf9ebBdW8Wyy5ujAUnbJfmzQ56Kkq5XtwErC/5+5RHyFYA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-transform-flow-strip-types" "^7.7.4"
+
+"@babel/preset-react@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.7.4.tgz#3fe2ea698d8fb536d8e7881a592c3c1ee8bf5707"
+  integrity sha512-j+vZtg0/8pQr1H8wKoaJyGL2IEk3rG/GIvua7Sec7meXVIvGycihlGMx5xcU00kqCJbwzHs18xTu3YfREOqQ+g==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-transform-react-display-name" "^7.7.4"
+    "@babel/plugin-transform-react-jsx" "^7.7.4"
+    "@babel/plugin-transform-react-jsx-self" "^7.7.4"
+    "@babel/plugin-transform-react-jsx-source" "^7.7.4"
+
+"@babel/preset-typescript@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.7.4.tgz#780059a78e6fa7f7a4c87f027292a86b31ce080a"
+  integrity sha512-rqrjxfdiHPsnuPur0jKrIIGQCIgoTWMTjlbWE69G4QJ6TIOVnnRnIJhUxNTL/VwDmEAVX08Tq3B1nirer5341w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-transform-typescript" "^7.7.4"
+
+"@babel/register@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.7.4.tgz#45a4956471a9df3b012b747f5781cc084ee8f128"
+  integrity sha512-/fmONZqL6ZMl9KJUYajetCrID6m0xmL4odX7v+Xvoxcv0DdbP/oO0TWIeLUCHqczQ6L6njDMqmqHFy2cp3FFsA==
+  dependencies:
+    find-cache-dir "^2.0.0"
+    lodash "^4.17.13"
+    make-dir "^2.1.0"
+    pirates "^4.0.0"
+    source-map-support "^0.5.16"
+
 "@babel/runtime@^7.1.2":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.4.tgz#b23a856751e4bf099262f867767889c0e3fe175b"
@@ -92,6 +835,13 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
+"@babel/runtime@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
+  integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
+  dependencies:
+    regenerator-runtime "^0.13.2"
+
 "@babel/template@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
@@ -574,11 +1324,6 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
   integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
 
-ansi-styles@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-  integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
 ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -586,14 +1331,6 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   dependencies:
     color-convert "^1.9.0"
 
-anymatch@^1.3.0:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
-  integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==
-  dependencies:
-    micromatch "^2.1.5"
-    normalize-path "^2.0.0"
-
 anymatch@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@@ -630,19 +1367,12 @@ argparse@^1.0.7:
   dependencies:
     sprintf-js "~1.0.2"
 
-arr-diff@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
-  integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
-  dependencies:
-    arr-flatten "^1.0.1"
-
 arr-diff@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
   integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
 
-arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+arr-flatten@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
   integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
@@ -682,11 +1412,6 @@ array-uniq@^1.0.1, array-uniq@^1.0.2:
   resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
   integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
 
-array-unique@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
-  integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
 array-unique@^0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
@@ -746,7 +1471,7 @@ astral-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
   integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
 
-async-each@^1.0.0, async-each@^1.0.1:
+async-each@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
   integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
@@ -796,63 +1521,7 @@ aws4@^1.8.0:
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c"
   integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==
 
-babel-cli@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1"
-  integrity sha1-UCq1SHTX24itALiHoGODzgPQAvE=
-  dependencies:
-    babel-core "^6.26.0"
-    babel-polyfill "^6.26.0"
-    babel-register "^6.26.0"
-    babel-runtime "^6.26.0"
-    commander "^2.11.0"
-    convert-source-map "^1.5.0"
-    fs-readdir-recursive "^1.0.0"
-    glob "^7.1.2"
-    lodash "^4.17.4"
-    output-file-sync "^1.1.2"
-    path-is-absolute "^1.0.1"
-    slash "^1.0.0"
-    source-map "^0.5.6"
-    v8flags "^2.1.1"
-  optionalDependencies:
-    chokidar "^1.6.1"
-
-babel-code-frame@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
-  integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
-  dependencies:
-    chalk "^1.1.3"
-    esutils "^2.0.2"
-    js-tokens "^3.0.2"
-
-babel-core@^6.26.0, babel-core@^6.26.3:
-  version "6.26.3"
-  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
-  integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-generator "^6.26.0"
-    babel-helpers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-register "^6.26.0"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    convert-source-map "^1.5.1"
-    debug "^2.6.9"
-    json5 "^0.5.1"
-    lodash "^4.17.4"
-    minimatch "^3.0.4"
-    path-is-absolute "^1.0.1"
-    private "^0.1.8"
-    slash "^1.0.0"
-    source-map "^0.5.7"
-
-babel-eslint@^10.0.1:
+babel-eslint@^10.0.3:
   version "10.0.3"
   resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a"
   integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==
@@ -864,593 +1533,14 @@ babel-eslint@^10.0.1:
     eslint-visitor-keys "^1.0.0"
     resolve "^1.12.0"
 
-babel-generator@^6.26.0:
-  version "6.26.1"
-  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
-  integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+babel-plugin-dynamic-import-node@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f"
+  integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==
   dependencies:
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    detect-indent "^4.0.0"
-    jsesc "^1.3.0"
-    lodash "^4.17.4"
-    source-map "^0.5.7"
-    trim-right "^1.0.1"
+    object.assign "^4.1.0"
 
-babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
-  integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=
-  dependencies:
-    babel-helper-explode-assignable-expression "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-builder-react-jsx@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0"
-  integrity sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    esutils "^2.0.2"
-
-babel-helper-call-delegate@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
-  integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=
-  dependencies:
-    babel-helper-hoist-variables "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-define-map@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
-  integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-helper-explode-assignable-expression@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
-  integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-function-name@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
-  integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=
-  dependencies:
-    babel-helper-get-function-arity "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-get-function-arity@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
-  integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-hoist-variables@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
-  integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-optimise-call-expression@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
-  integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-regex@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
-  integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-helper-remap-async-to-generator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
-  integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-replace-supers@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
-  integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo=
-  dependencies:
-    babel-helper-optimise-call-expression "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helpers@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
-  integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-loader@^7.1.5:
-  version "7.1.5"
-  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
-  integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==
-  dependencies:
-    find-cache-dir "^1.0.0"
-    loader-utils "^1.0.2"
-    mkdirp "^0.5.1"
-
-babel-messages@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
-  integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-add-module-exports@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
-  integrity sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=
-
-babel-plugin-check-es2015-constants@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
-  integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-syntax-async-functions@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
-  integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=
-
-babel-plugin-syntax-class-properties@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
-  integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=
-
-babel-plugin-syntax-dynamic-import@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
-  integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=
-
-babel-plugin-syntax-exponentiation-operator@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
-  integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=
-
-babel-plugin-syntax-flow@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
-  integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=
-
-babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
-  integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
-
-babel-plugin-syntax-object-rest-spread@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
-  integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
-
-babel-plugin-syntax-trailing-function-commas@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
-  integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=
-
-babel-plugin-transform-async-to-generator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
-  integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=
-  dependencies:
-    babel-helper-remap-async-to-generator "^6.24.1"
-    babel-plugin-syntax-async-functions "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-builtin-extend@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-builtin-extend/-/babel-plugin-transform-builtin-extend-1.1.2.tgz#5e96fecf58b8fa1ed74efcad88475b2af3c9116e"
-  integrity sha1-Xpb+z1i4+h7XTvytiEdbKvPJEW4=
-  dependencies:
-    babel-runtime "^6.2.0"
-    babel-template "^6.3.0"
-
-babel-plugin-transform-class-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
-  integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-plugin-syntax-class-properties "^6.8.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-arrow-functions@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
-  integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
-  integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoping@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
-  integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-plugin-transform-es2015-classes@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
-  integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=
-  dependencies:
-    babel-helper-define-map "^6.24.1"
-    babel-helper-function-name "^6.24.1"
-    babel-helper-optimise-call-expression "^6.24.1"
-    babel-helper-replace-supers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-computed-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
-  integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-destructuring@^6.22.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
-  integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
-  integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-for-of@^6.22.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
-  integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-function-name@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
-  integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-literals@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
-  integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-modules-amd@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
-  integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=
-  dependencies:
-    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
-  version "6.26.2"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
-  integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==
-  dependencies:
-    babel-plugin-transform-strict-mode "^6.24.1"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-types "^6.26.0"
-
-babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
-  integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=
-  dependencies:
-    babel-helper-hoist-variables "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-umd@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
-  integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg=
-  dependencies:
-    babel-plugin-transform-es2015-modules-amd "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-object-super@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
-  integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40=
-  dependencies:
-    babel-helper-replace-supers "^6.24.1"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-parameters@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
-  integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=
-  dependencies:
-    babel-helper-call-delegate "^6.24.1"
-    babel-helper-get-function-arity "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
-  integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-spread@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
-  integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-sticky-regex@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
-  integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw=
-  dependencies:
-    babel-helper-regex "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-template-literals@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
-  integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
-  integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-unicode-regex@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
-  integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek=
-  dependencies:
-    babel-helper-regex "^6.24.1"
-    babel-runtime "^6.22.0"
-    regexpu-core "^2.0.0"
-
-babel-plugin-transform-exponentiation-operator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
-  integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=
-  dependencies:
-    babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
-    babel-plugin-syntax-exponentiation-operator "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-flow-strip-types@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
-  integrity sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=
-  dependencies:
-    babel-plugin-syntax-flow "^6.18.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-object-rest-spread@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
-  integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=
-  dependencies:
-    babel-plugin-syntax-object-rest-spread "^6.8.0"
-    babel-runtime "^6.26.0"
-
-babel-plugin-transform-react-display-name@^6.23.0:
-  version "6.25.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1"
-  integrity sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-react-jsx-self@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e"
-  integrity sha1-322AqdomEqEh5t3XVYvL7PBuY24=
-  dependencies:
-    babel-plugin-syntax-jsx "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-react-jsx-source@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6"
-  integrity sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=
-  dependencies:
-    babel-plugin-syntax-jsx "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-react-jsx@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3"
-  integrity sha1-hAoCjn30YN/DotKfDA2R9jduZqM=
-  dependencies:
-    babel-helper-builder-react-jsx "^6.24.1"
-    babel-plugin-syntax-jsx "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-regenerator@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
-  integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=
-  dependencies:
-    regenerator-transform "^0.10.0"
-
-babel-plugin-transform-runtime@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
-  integrity sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-strict-mode@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
-  integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-polyfill@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
-  integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=
-  dependencies:
-    babel-runtime "^6.26.0"
-    core-js "^2.5.0"
-    regenerator-runtime "^0.10.5"
-
-babel-preset-es2015@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
-  integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=
-  dependencies:
-    babel-plugin-check-es2015-constants "^6.22.0"
-    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoping "^6.24.1"
-    babel-plugin-transform-es2015-classes "^6.24.1"
-    babel-plugin-transform-es2015-computed-properties "^6.24.1"
-    babel-plugin-transform-es2015-destructuring "^6.22.0"
-    babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
-    babel-plugin-transform-es2015-for-of "^6.22.0"
-    babel-plugin-transform-es2015-function-name "^6.24.1"
-    babel-plugin-transform-es2015-literals "^6.22.0"
-    babel-plugin-transform-es2015-modules-amd "^6.24.1"
-    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
-    babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
-    babel-plugin-transform-es2015-modules-umd "^6.24.1"
-    babel-plugin-transform-es2015-object-super "^6.24.1"
-    babel-plugin-transform-es2015-parameters "^6.24.1"
-    babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
-    babel-plugin-transform-es2015-spread "^6.22.0"
-    babel-plugin-transform-es2015-sticky-regex "^6.24.1"
-    babel-plugin-transform-es2015-template-literals "^6.22.0"
-    babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
-    babel-plugin-transform-es2015-unicode-regex "^6.24.1"
-    babel-plugin-transform-regenerator "^6.24.1"
-
-babel-preset-es2016@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b"
-  integrity sha1-+QC/k+LrwNJ235uKtZck6/2Vn4s=
-  dependencies:
-    babel-plugin-transform-exponentiation-operator "^6.24.1"
-
-babel-preset-es2017@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1"
-  integrity sha1-WXvq37n38gi8/YoS6bKym4svFNE=
-  dependencies:
-    babel-plugin-syntax-trailing-function-commas "^6.22.0"
-    babel-plugin-transform-async-to-generator "^6.24.1"
-
-babel-preset-flow@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
-  integrity sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=
-  dependencies:
-    babel-plugin-transform-flow-strip-types "^6.22.0"
-
-babel-preset-react@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
-  integrity sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=
-  dependencies:
-    babel-plugin-syntax-jsx "^6.3.13"
-    babel-plugin-transform-react-display-name "^6.23.0"
-    babel-plugin-transform-react-jsx "^6.24.1"
-    babel-plugin-transform-react-jsx-self "^6.22.0"
-    babel-plugin-transform-react-jsx-source "^6.22.0"
-    babel-preset-flow "^6.23.0"
-
-babel-register@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
-  integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
-  dependencies:
-    babel-core "^6.26.0"
-    babel-runtime "^6.26.0"
-    core-js "^2.5.0"
-    home-or-tmp "^2.0.0"
-    lodash "^4.17.4"
-    mkdirp "^0.5.1"
-    source-map-support "^0.4.15"
-
-babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -1458,47 +1548,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtim
     core-js "^2.4.0"
     regenerator-runtime "^0.11.0"
 
-babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
-  integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    lodash "^4.17.4"
-
-babel-traverse@^6.24.1, babel-traverse@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
-  integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    debug "^2.6.8"
-    globals "^9.18.0"
-    invariant "^2.2.2"
-    lodash "^4.17.4"
-
-babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
-  integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
-  dependencies:
-    babel-runtime "^6.26.0"
-    esutils "^2.0.2"
-    lodash "^4.17.4"
-    to-fast-properties "^1.0.3"
-
-babylon@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
-  integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
-
 backo2@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
@@ -1622,15 +1671,6 @@ brace-expansion@^1.1.7:
     balanced-match "^1.0.0"
     concat-map "0.0.1"
 
-braces@^1.8.2:
-  version "1.8.5"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
-  integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
-  dependencies:
-    expand-range "^1.8.1"
-    preserve "^0.2.0"
-    repeat-element "^1.1.2"
-
 braces@^2.3.1, braces@^2.3.2:
   version "2.3.2"
   resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -1733,6 +1773,15 @@ browserify-zlib@^0.2.0:
   dependencies:
     pako "~1.0.5"
 
+browserslist@^4.6.0, browserslist@^4.8.2:
+  version "4.8.2"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289"
+  integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==
+  dependencies:
+    caniuse-lite "^1.0.30001015"
+    electron-to-chromium "^1.3.322"
+    node-releases "^1.1.42"
+
 browserslist@^4.8.0:
   version "4.8.0"
   resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.0.tgz#6f06b0f974a7cc3a84babc2ccc56493668e3c789"
@@ -1786,6 +1835,11 @@ buffer@^4.3.0:
     ieee754 "^1.1.4"
     isarray "^1.0.0"
 
+builtin-modules@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+  integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
+
 builtin-status-codes@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -1885,7 +1939,7 @@ camelcase@^5.0.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
-caniuse-lite@^1.0.30001012:
+caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001015:
   version "1.0.30001015"
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0"
   integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==
@@ -1905,7 +1959,7 @@ chain-function@^1.0.0:
   resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc"
   integrity sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==
 
-chalk@2.4.2, "chalk@^1.1.3 || 2.x", chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@2.4.2, "chalk@^1.1.3 || 2.x", chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -1914,17 +1968,6 @@ chalk@2.4.2, "chalk@^1.1.3 || 2.x", chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, ch
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
-chalk@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
-  integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
-  dependencies:
-    ansi-styles "^2.2.1"
-    escape-string-regexp "^1.0.2"
-    has-ansi "^2.0.0"
-    strip-ansi "^3.0.0"
-    supports-color "^2.0.0"
-
 character-entities-html4@^1.0.0:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.3.tgz#5ce6e01618e47048ac22f34f7f39db5c6fd679ef"
@@ -1950,23 +1993,7 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-chokidar@^1.6.1:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
-  integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=
-  dependencies:
-    anymatch "^1.3.0"
-    async-each "^1.0.0"
-    glob-parent "^2.0.0"
-    inherits "^2.0.1"
-    is-binary-path "^1.0.0"
-    is-glob "^2.0.0"
-    path-is-absolute "^1.0.0"
-    readdirp "^2.0.0"
-  optionalDependencies:
-    fsevents "^1.0.0"
-
-chokidar@^2.0.2, chokidar@^2.1.2:
+chokidar@^2.0.2, chokidar@^2.1.2, chokidar@^2.1.8:
   version "2.1.8"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
   integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
@@ -2129,11 +2156,16 @@ commander@2.15.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
   integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
 
-commander@^2.11.0, commander@^2.20.0:
+commander@^2.12.1, commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
 
+commander@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c"
+  integrity sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==
+
 commondir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -2229,7 +2261,7 @@ content-type@^1.0.2, content-type@~1.0.4:
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
-convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
+convert-source-map@^1.1.0, convert-source-map@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
   integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@@ -2258,12 +2290,20 @@ copy-descriptor@^0.1.0:
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
   integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
 
+core-js-compat@^3.4.7:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.5.0.tgz#5a11a619a9e9dd2dcf1c742b2060bc4a2143e5b6"
+  integrity sha512-E7iJB72svRjJTnm9HDvujzNVMCm3ZcDYEedkJ/sDTNsy/0yooCd9Cg7GSzE7b4e0LfIkjijdB1tqg0pGwxWeWg==
+  dependencies:
+    browserslist "^4.8.2"
+    semver "^6.3.0"
+
 core-js@^1.0.0:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
   integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
 
-core-js@^2.4.0, core-js@^2.5.0:
+core-js@^2.4.0:
   version "2.6.10"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
   integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
@@ -2411,7 +2451,7 @@ date-names@^0.1.11:
   resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.13.tgz#c4358f6f77c8056e2f5ea68fdbb05f0bf1e53bd0"
   integrity sha512-IxxoeD9tdx8pXVcmqaRlPvrXIsSrSrIZzfzlOkm9u+hyzKp5Wk/odt9O/gd7Ockzy8n/WHeEpTVJ2bF3mMV4LA==
 
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
   integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -2524,13 +2564,6 @@ detect-file@^1.0.0:
   resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
   integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
 
-detect-indent@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
-  integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
-  dependencies:
-    repeating "^2.0.0"
-
 detect-libc@^1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
@@ -2564,6 +2597,11 @@ diff@3.5.0, diff@^3.5.0:
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
 
+diff@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
+  integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
+
 diffie-hellman@^5.0.0:
   version "5.0.3"
   resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -2684,7 +2722,7 @@ ee-first@1.1.1:
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
   integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
 
-electron-to-chromium@^1.3.317:
+electron-to-chromium@^1.3.317, electron-to-chromium@^1.3.322:
   version "1.3.322"
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
   integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==
@@ -2893,7 +2931,7 @@ escape-html@^1.0.3, escape-html@~1.0.3:
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -3073,7 +3111,7 @@ estree-walker@^0.6.1:
   resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
   integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
 
-esutils@^2.0.2:
+esutils@^2.0.0, esutils@^2.0.2:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
   integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
@@ -3123,13 +3161,6 @@ execall@^1.0.0:
   dependencies:
     clone-regexp "^1.0.0"
 
-expand-brackets@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
-  integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
-  dependencies:
-    is-posix-bracket "^0.1.0"
-
 expand-brackets@^2.1.4:
   version "2.1.4"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -3143,13 +3174,6 @@ expand-brackets@^2.1.4:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-expand-range@^1.8.1:
-  version "1.8.2"
-  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
-  integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
-  dependencies:
-    fill-range "^2.1.0"
-
 expand-tilde@^2.0.0, expand-tilde@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
@@ -3211,13 +3235,6 @@ external-editor@^3.0.3:
     iconv-lite "^0.4.24"
     tmp "^0.0.33"
 
-extglob@^0.3.1:
-  version "0.3.2"
-  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
-  integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
-  dependencies:
-    is-extglob "^1.0.0"
-
 extglob@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@@ -3337,27 +3354,11 @@ file-saver@^1.3.3:
   resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8"
   integrity sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg==
 
-filename-regex@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
-  integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
 filesize@3.5.6:
   version "3.5.6"
   resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a"
   integrity sha1-X9mPPqyU7JUW747VeC+thKAaCho=
 
-fill-range@^2.1.0:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
-  integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
-  dependencies:
-    is-number "^2.1.0"
-    isobject "^2.0.0"
-    randomatic "^3.0.0"
-    repeat-element "^1.1.2"
-    repeat-string "^1.5.2"
-
 fill-range@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -3388,16 +3389,7 @@ finalhandler@1.1.2:
     statuses "~1.5.0"
     unpipe "~1.0.0"
 
-find-cache-dir@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
-  integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=
-  dependencies:
-    commondir "^1.0.1"
-    make-dir "^1.0.0"
-    pkg-dir "^2.0.0"
-
-find-cache-dir@^2.1.0:
+find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
   integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
@@ -3414,7 +3406,7 @@ find-up@4.1.0:
     locate-path "^5.0.0"
     path-exists "^4.0.0"
 
-find-up@^2.0.0, find-up@^2.1.0:
+find-up@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
   integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
@@ -3500,18 +3492,11 @@ follow-redirects@^1.0.0:
   dependencies:
     debug "^3.0.0"
 
-for-in@^1.0.1, for-in@^1.0.2:
+for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
   integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
 
-for-own@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
-  integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
-  dependencies:
-    for-in "^1.0.1"
-
 foreachasync@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6"
@@ -3569,7 +3554,7 @@ fs-minipass@^1.2.5:
   dependencies:
     minipass "^2.6.0"
 
-fs-readdir-recursive@^1.0.0:
+fs-readdir-recursive@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27"
   integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==
@@ -3589,7 +3574,7 @@ fs.realpath@^1.0.0:
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
 
-fsevents@^1.0.0, fsevents@^1.2.7:
+fsevents@^1.2.7:
   version "1.2.9"
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
   integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==
@@ -3691,21 +3676,6 @@ gfm.css@^1.1.1:
   resolved "https://registry.yarnpkg.com/gfm.css/-/gfm.css-1.1.2.tgz#94acfa600672663b9dd0fd4b6ee5d11c8dbc161e"
   integrity sha512-KhK3rqxMj+UTLRxWnfUA5n8XZYMWfHrrcCxtWResYR2B3hWIqBM6v9FPGZSlVuX+ScLewizOvNkjYXuPs95ThQ==
 
-glob-base@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
-  integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
-  dependencies:
-    glob-parent "^2.0.0"
-    is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
-  integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
-  dependencies:
-    is-glob "^2.0.0"
-
 glob-parent@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@@ -3754,7 +3724,7 @@ glob@^5.0.14:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.1.6"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
   integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -3807,11 +3777,6 @@ globals@^11.1.0, globals@^11.7.0:
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
   integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
-globals@^9.18.0:
-  version "9.18.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
-  integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
-
 globby@^9.0.0:
   version "9.2.0"
   resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
@@ -3838,7 +3803,7 @@ gonzales-pe@^4.2.3:
   dependencies:
     minimist "1.1.x"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
   integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
@@ -3861,13 +3826,6 @@ har-validator@~5.1.0:
     ajv "^6.5.5"
     har-schema "^2.0.0"
 
-has-ansi@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
-  integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
-  dependencies:
-    ansi-regex "^2.0.0"
-
 has-binary2@~1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
@@ -3980,14 +3938,6 @@ hoist-non-react-statics@^3.3.0:
   dependencies:
     react-is "^16.7.0"
 
-home-or-tmp@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
-  integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.1"
-
 homedir-polyfill@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
@@ -4388,18 +4338,6 @@ is-directory@^0.3.1:
   resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
   integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
 
-is-dotfile@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
-  integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
-  integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
-  dependencies:
-    is-primitive "^2.0.0"
-
 is-equal@^1.5.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/is-equal/-/is-equal-1.6.1.tgz#74fafde5060fcaf187041c05f11f0b9f020bb9b3"
@@ -4436,23 +4374,11 @@ is-extendable@^1.0.1:
   dependencies:
     is-plain-object "^2.0.4"
 
-is-extglob@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
-  integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
 is-extglob@^2.1.0, is-extglob@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
   integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
 
-is-finite@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
-  integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
-  dependencies:
-    number-is-nan "^1.0.0"
-
 is-fullwidth-code-point@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -4475,13 +4401,6 @@ is-generator-function@^1.0.7:
   resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
   integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==
 
-is-glob@^2.0.0, is-glob@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
-  integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
-  dependencies:
-    is-extglob "^1.0.0"
-
 is-glob@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
@@ -4528,13 +4447,6 @@ is-number-object@^1.0.3:
   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799"
   integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=
 
-is-number@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
-  integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
-  dependencies:
-    kind-of "^3.0.2"
-
 is-number@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -4542,11 +4454,6 @@ is-number@^3.0.0:
   dependencies:
     kind-of "^3.0.2"
 
-is-number@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
-  integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
 is-number@^7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@@ -4569,16 +4476,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
-is-posix-bracket@^0.1.0:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
-  integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
-  integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
 is-promise@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
@@ -4787,16 +4684,16 @@ jquery@^3.3.1:
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
   integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
 
+js-levenshtein@^1.1.3:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
+  integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+
 "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
   integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
 
-js-tokens@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
-  integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-
 js-yaml@^3.13.0, js-yaml@^3.13.1:
   version "3.13.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
@@ -4810,11 +4707,6 @@ jsbn@~0.1.0:
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
-jsesc@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
-  integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
-
 jsesc@^2.5.1:
   version "2.5.2"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -4850,11 +4742,6 @@ json-stringify-safe@~5.0.1:
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
   integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
 
-json5@^0.5.1:
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
-  integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
-
 json5@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
@@ -5219,14 +5106,7 @@ lru-cache@^5.1.1:
   dependencies:
     yallist "^3.0.2"
 
-make-dir@^1.0.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
-  integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
-  dependencies:
-    pify "^3.0.0"
-
-make-dir@^2.0.0:
+make-dir@^2.0.0, make-dir@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
   integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@@ -5295,11 +5175,6 @@ markdown-table@^1.1.0:
   resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60"
   integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
 
-math-random@^1.0.1:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
-  integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
-
 mathml-tag-names@^2.0.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc"
@@ -5417,25 +5292,6 @@ merge2@^1.2.3:
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
   integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
 
-micromatch@^2.1.5:
-  version "2.3.11"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
-  integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
-  dependencies:
-    arr-diff "^2.0.0"
-    array-unique "^0.2.1"
-    braces "^1.8.2"
-    expand-brackets "^0.1.4"
-    extglob "^0.3.1"
-    filename-regex "^2.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.1"
-    kind-of "^3.0.2"
-    normalize-path "^2.0.1"
-    object.omit "^2.0.0"
-    parse-glob "^3.0.4"
-    regex-cache "^0.4.2"
-
 micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
@@ -5733,6 +5589,11 @@ node-libs-browser@^2.2.1:
     util "^0.11.0"
     vm-browserify "^1.0.1"
 
+node-modules-regexp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
+  integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
+
 node-pre-gyp@^0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
@@ -5749,7 +5610,7 @@ node-pre-gyp@^0.12.0:
     semver "^5.3.0"
     tar "^4"
 
-node-releases@^1.1.41:
+node-releases@^1.1.41, node-releases@^1.1.42:
   version "1.1.42"
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.42.tgz#a999f6a62f8746981f6da90627a8d2fc090bbad7"
   integrity sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA==
@@ -5774,7 +5635,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
     semver "2 || 3 || 4 || 5"
     validate-npm-package-license "^3.0.1"
 
-normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
+normalize-path@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
   integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
@@ -5912,14 +5773,6 @@ object.fromentries@^2.0.1:
     function-bind "^1.1.1"
     has "^1.0.3"
 
-object.omit@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
-  integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
-  dependencies:
-    for-own "^0.1.4"
-    is-extendable "^0.1.1"
-
 object.pick@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@@ -5997,7 +5850,7 @@ os-locale@^3.0.0, os-locale@^3.1.0:
     lcid "^2.0.0"
     mem "^4.0.0"
 
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
@@ -6010,15 +5863,6 @@ osenv@^0.1.4:
     os-homedir "^1.0.0"
     os-tmpdir "^1.0.0"
 
-output-file-sync@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76"
-  integrity sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=
-  dependencies:
-    graceful-fs "^4.1.4"
-    mkdirp "^0.5.1"
-    object-assign "^4.1.0"
-
 p-defer@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
@@ -6124,16 +5968,6 @@ parse-entities@^1.0.2, parse-entities@^1.1.0:
     is-decimal "^1.0.0"
     is-hexadecimal "^1.0.0"
 
-parse-glob@^3.0.4:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
-  integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
-  dependencies:
-    glob-base "^0.3.0"
-    is-dotfile "^1.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.0"
-
 parse-json@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -6191,7 +6025,7 @@ path-exists@^4.0.0:
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
   integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
 
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
   integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
@@ -6261,12 +6095,12 @@ pify@^4.0.0, pify@^4.0.1:
   resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
-pkg-dir@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
-  integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
+pirates@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
+  integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
   dependencies:
-    find-up "^2.1.0"
+    node-modules-regexp "^1.0.0"
 
 pkg-dir@^3.0.0:
   version "3.0.0"
@@ -6410,11 +6244,6 @@ prelude-ls@~1.1.2:
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
   integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 
-preserve@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-  integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
 pretty-format@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
@@ -6425,7 +6254,7 @@ pretty-format@^24.9.0:
     ansi-styles "^3.2.0"
     react-is "^16.8.4"
 
-private@^0.1.6, private@^0.1.8:
+private@^0.1.6:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
   integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
@@ -6600,15 +6429,6 @@ raf@^3.1.0:
   dependencies:
     performance-now "^2.1.0"
 
-randomatic@^3.0.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
-  integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
-  dependencies:
-    is-number "^4.0.0"
-    kind-of "^6.0.0"
-    math-random "^1.0.1"
-
 randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -6803,7 +6623,7 @@ readable-stream@^3.1.1:
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-readdirp@^2.0.0, readdirp@^2.2.1:
+readdirp@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
   integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
@@ -6842,16 +6662,18 @@ redux@^3.7.2:
     loose-envify "^1.1.0"
     symbol-observable "^1.0.3"
 
-regenerate@^1.2.1:
+regenerate-unicode-properties@^8.1.0:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
+  integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==
+  dependencies:
+    regenerate "^1.4.0"
+
+regenerate@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
   integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
 
-regenerator-runtime@^0.10.5:
-  version "0.10.5"
-  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
-  integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=
-
 regenerator-runtime@^0.11.0:
   version "0.11.1"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
@@ -6862,22 +6684,13 @@ regenerator-runtime@^0.13.2:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
   integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
 
-regenerator-transform@^0.10.0:
-  version "0.10.1"
-  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
-  integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==
+regenerator-transform@^0.14.0:
+  version "0.14.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
+  integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==
   dependencies:
-    babel-runtime "^6.18.0"
-    babel-types "^6.19.0"
     private "^0.1.6"
 
-regex-cache@^0.4.2:
-  version "0.4.4"
-  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
-  integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
-  dependencies:
-    is-equal-shallow "^0.1.3"
-
 regex-not@^1.0.0, regex-not@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@@ -6891,14 +6704,17 @@ regexpp@^2.0.1:
   resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
   integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
 
-regexpu-core@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
-  integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=
+regexpu-core@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
+  integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==
   dependencies:
-    regenerate "^1.2.1"
-    regjsgen "^0.2.0"
-    regjsparser "^0.1.4"
+    regenerate "^1.4.0"
+    regenerate-unicode-properties "^8.1.0"
+    regjsgen "^0.5.0"
+    regjsparser "^0.6.0"
+    unicode-match-property-ecmascript "^1.0.4"
+    unicode-match-property-value-ecmascript "^1.1.0"
 
 registry-auth-token@4.0.0:
   version "4.0.0"
@@ -6908,15 +6724,15 @@ registry-auth-token@4.0.0:
     rc "^1.2.8"
     safe-buffer "^5.0.1"
 
-regjsgen@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
-  integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
+regjsgen@^0.5.0:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c"
+  integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==
 
-regjsparser@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
-  integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=
+regjsparser@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c"
+  integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==
   dependencies:
     jsesc "~0.5.0"
 
@@ -6980,18 +6796,11 @@ repeat-element@^1.1.2:
   resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
   integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
 
-repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1:
+repeat-string@^1.5.4, repeat-string@^1.6.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
   integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
 
-repeating@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
-  integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
-  dependencies:
-    is-finite "^1.0.0"
-
 replace-ext@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
@@ -7088,7 +6897,7 @@ resolve-url@^0.2.1:
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.8.1:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
   integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
@@ -7334,11 +7143,6 @@ sinon@^5.0.7:
     supports-color "^5.4.0"
     type-detect "^4.0.8"
 
-slash@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
-  integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
-
 slash@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
@@ -7561,14 +7365,7 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.4.15:
-  version "0.4.18"
-  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
-  integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
-  dependencies:
-    source-map "^0.5.6"
-
-source-map-support@~0.5.12:
+source-map-support@^0.5.16, source-map-support@~0.5.12:
   version "0.5.16"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
   integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
@@ -7581,7 +7378,7 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
-source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -7970,11 +7767,6 @@ supports-color@6.1.0, supports-color@^6.1.0:
   dependencies:
     has-flag "^3.0.0"
 
-supports-color@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
-  integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
 supports-color@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
@@ -8108,11 +7900,6 @@ to-arraybuffer@^1.0.0:
   resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
   integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
 
-to-fast-properties@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-  integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
-
 to-fast-properties@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -8173,11 +7960,6 @@ trim-newlines@^2.0.0:
   resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
   integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
 
-trim-right@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
-  integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
-
 trim-trailing-lines@^1.0.0:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz#d2f1e153161152e9f02fabc670fb40bec2ea2e3a"
@@ -8193,11 +7975,37 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-tslib@^1.8.1, tslib@^1.9.0:
+tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
 
+tslint@^5.20.1:
+  version "5.20.1"
+  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d"
+  integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    builtin-modules "^1.1.1"
+    chalk "^2.3.0"
+    commander "^2.12.1"
+    diff "^4.0.1"
+    glob "^7.1.1"
+    js-yaml "^3.13.1"
+    minimatch "^3.0.4"
+    mkdirp "^0.5.1"
+    resolve "^1.3.2"
+    semver "^5.3.0"
+    tslib "^1.8.0"
+    tsutils "^2.29.0"
+
+tsutils@^2.29.0:
+  version "2.29.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
+  integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
+  dependencies:
+    tslib "^1.8.1"
+
 tsutils@^3.17.1:
   version "3.17.1"
   resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
@@ -8252,6 +8060,11 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
+typescript@^3.7.3:
+  version "3.7.3"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69"
+  integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==
+
 ua-parser-js@^0.7.18:
   version "0.7.20"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
@@ -8275,6 +8088,29 @@ unhomoglyph@^1.0.2:
   resolved "https://registry.yarnpkg.com/unhomoglyph/-/unhomoglyph-1.0.3.tgz#8d3551622b57754e10a831bf81442d7f15d1ddfd"
   integrity sha512-PC/OAHE8aiTK0Gfmy0PxOlePazRn+BeCM1r4kFtkHgEnkJZgJoI7yD2yUEjsfSdLXKU1FSt/EcIZvNoKazYUTw==
 
+unicode-canonical-property-names-ecmascript@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
+  integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
+
+unicode-match-property-ecmascript@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
+  integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
+  dependencies:
+    unicode-canonical-property-names-ecmascript "^1.0.4"
+    unicode-property-aliases-ecmascript "^1.0.4"
+
+unicode-match-property-value-ecmascript@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277"
+  integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==
+
+unicode-property-aliases-ecmascript@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57"
+  integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==
+
 unified@^7.0.0:
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13"
@@ -8427,11 +8263,6 @@ use@^3.1.0:
   resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
   integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
 
-user-home@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
-  integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA=
-
 useragent@2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
@@ -8474,13 +8305,6 @@ v8-compile-cache@2.0.3:
   resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
   integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
 
-v8flags@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
-  integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=
-  dependencies:
-    user-home "^1.1.1"
-
 validate-npm-package-license@^3.0.1:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"

From 59ddefdb8fe904d133a7266e01b6c79b5ff86c26 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:39:01 -0700
Subject: [PATCH 06/86] Disable tests for new TypeScript build

We're switching to Jest anyways, and getting these things to run is basically impossible at the moment.
---
 .buildkite/pipeline.yaml | 106 +++++++++++++++++++--------------------
 1 file changed, 53 insertions(+), 53 deletions(-)

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index 8bbcdf78a4..632ab7adca 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -53,59 +53,59 @@ steps:
           image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
           propagate-environment: true
 
-  - label: ":karma: Tests"
-    agents:
-      # We use a medium sized instance instead of the normal small ones because
-      # webpack loves to gorge itself on resources.
-      queue: "medium"
-    command:
-      # Install chrome
-      - "echo '--- Installing Chrome'"
-      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
-      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
-      - "apt-get update"
-      - "apt-get install -y google-chrome-stable"
-      # Run tests
-      # TODO: Remove hacky chmod for BuildKite
-      - "chmod +x ./scripts/ci/*.sh"
-      - "chmod +x ./scripts/*"
-      - "echo '--- Installing Dependencies'"
-      - "./scripts/ci/install-deps.sh"
-      - "echo '+++ Running Tests'"
-      - "./scripts/ci/unit-tests.sh"
-    env:
-      CHROME_BIN: "/usr/bin/google-chrome-stable"
-    plugins:
-      - docker#v3.0.1:
-          image: "node:10"
-          propagate-environment: true
-
-  - label: "🔧 Riot Tests"
-    agents:
-      # We use a medium sized instance instead of the normal small ones because
-      # webpack loves to gorge itself on resources.
-      queue: "medium"
-    command:
-      # Install chrome
-      - "echo '--- Installing Chrome'"
-      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
-      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
-      - "apt-get update"
-      - "apt-get install -y google-chrome-stable"
-      # Run tests
-      # TODO: Remove hacky chmod for BuildKite
-      - "chmod +x ./scripts/ci/*.sh"
-      - "chmod +x ./scripts/*"
-      - "echo '--- Installing Dependencies'"
-      - "./scripts/ci/install-deps.sh"
-      - "echo '+++ Running Tests'"
-      - "./scripts/ci/riot-unit-tests.sh"
-    env:
-      CHROME_BIN: "/usr/bin/google-chrome-stable"
-    plugins:
-      - docker#v3.0.1:
-          image: "node:10"
-          propagate-environment: true
+#  - label: ":karma: Tests"
+#    agents:
+#      # We use a medium sized instance instead of the normal small ones because
+#      # webpack loves to gorge itself on resources.
+#      queue: "medium"
+#    command:
+#      # Install chrome
+#      - "echo '--- Installing Chrome'"
+#      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
+#      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
+#      - "apt-get update"
+#      - "apt-get install -y google-chrome-stable"
+#      # Run tests
+#      # TODO: Remove hacky chmod for BuildKite
+#      - "chmod +x ./scripts/ci/*.sh"
+#      - "chmod +x ./scripts/*"
+#      - "echo '--- Installing Dependencies'"
+#      - "./scripts/ci/install-deps.sh"
+#      - "echo '+++ Running Tests'"
+#      - "./scripts/ci/unit-tests.sh"
+#    env:
+#      CHROME_BIN: "/usr/bin/google-chrome-stable"
+#    plugins:
+#      - docker#v3.0.1:
+#          image: "node:10"
+#          propagate-environment: true
+#
+#  - label: "🔧 Riot Tests"
+#    agents:
+#      # We use a medium sized instance instead of the normal small ones because
+#      # webpack loves to gorge itself on resources.
+#      queue: "medium"
+#    command:
+#      # Install chrome
+#      - "echo '--- Installing Chrome'"
+#      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
+#      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
+#      - "apt-get update"
+#      - "apt-get install -y google-chrome-stable"
+#      # Run tests
+#      # TODO: Remove hacky chmod for BuildKite
+#      - "chmod +x ./scripts/ci/*.sh"
+#      - "chmod +x ./scripts/*"
+#      - "echo '--- Installing Dependencies'"
+#      - "./scripts/ci/install-deps.sh"
+#      - "echo '+++ Running Tests'"
+#      - "./scripts/ci/riot-unit-tests.sh"
+#    env:
+#      CHROME_BIN: "/usr/bin/google-chrome-stable"
+#    plugins:
+#      - docker#v3.0.1:
+#          image: "node:10"
+#          propagate-environment: true
 
   - label: "🌐 i18n"
     command:

From f5264db0282c40227c66a5a503145d4b4a69e17b Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 14:44:46 -0700
Subject: [PATCH 07/86] Disable end-to-end tests too

They rely on a working riot-web build, which this is not.
---
 .buildkite/pipeline.yaml | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index 632ab7adca..e4a0e5dd4a 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -35,24 +35,24 @@ steps:
       - docker#v3.0.1:
           image: "node:12"
 
-  - label: ":chains: End-to-End Tests"
-    agents:
-      # We use a xlarge sized instance instead of the normal small ones because
-      # e2e tests otherwise take +-8min
-      queue: "xlarge"
-    command:
-      # TODO: Remove hacky chmod for BuildKite
-      - "echo '--- Setup'"
-      - "chmod +x ./scripts/ci/*.sh"
-      - "chmod +x ./scripts/*"
-      - "echo '--- Install js-sdk'"
-      - "./scripts/ci/install-deps.sh"
-      - "./scripts/ci/end-to-end-tests.sh"
-    plugins:
-      - docker#v3.0.1:
-          image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
-          propagate-environment: true
-
+#  - label: ":chains: End-to-End Tests"
+#    agents:
+#      # We use a xlarge sized instance instead of the normal small ones because
+#      # e2e tests otherwise take +-8min
+#      queue: "xlarge"
+#    command:
+#      # TODO: Remove hacky chmod for BuildKite
+#      - "echo '--- Setup'"
+#      - "chmod +x ./scripts/ci/*.sh"
+#      - "chmod +x ./scripts/*"
+#      - "echo '--- Install js-sdk'"
+#      - "./scripts/ci/install-deps.sh"
+#      - "./scripts/ci/end-to-end-tests.sh"
+#    plugins:
+#      - docker#v3.0.1:
+#          image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
+#          propagate-environment: true
+#
 #  - label: ":karma: Tests"
 #    agents:
 #      # We use a medium sized instance instead of the normal small ones because

From 225695ab5c8f597252bf4b793ce88e2f22d73766 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 19:33:08 -0700
Subject: [PATCH 08/86] Fix exports for rate limited functions and
 MatrixClientPeg

MatrixClientPeg in particular doesn't work very well with this.
---
 src/MatrixClientPeg.js                   | 5 +++--
 src/components/structures/RoomView.js    | 2 +-
 src/components/views/rooms/MemberList.js | 4 ++--
 src/components/views/rooms/RoomList.js   | 4 ++--
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 51ac7acb37..4d293b7e34 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -48,7 +48,7 @@ interface MatrixClientCreds {
  * This module provides a singleton instance of this class so the 'current'
  * Matrix Client object is available easily.
  */
-class MatrixClientPeg {
+class _MatrixClientPeg {
     constructor() {
         this.matrixClient = null;
         this._justRegisteredUserId = null;
@@ -245,6 +245,7 @@ class MatrixClientPeg {
 }
 
 if (!global.mxMatrixClientPeg) {
-    global.mxMatrixClientPeg = new MatrixClientPeg();
+    global.mxMatrixClientPeg = new _MatrixClientPeg();
 }
 export default global.mxMatrixClientPeg;
+export const MatrixClientPeg = global.mxMatrixClientPeg;
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index d78c9923c2..2f8d274866 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -887,7 +887,7 @@ module.exports = createReactClass({
 
     // rate limited because a power level change will emit an event for every
     // member in the room.
-    _updateRoomMembers: new rate_limited_func(function(dueToMember) {
+    _updateRoomMembers: rate_limited_func(function(dueToMember) {
         // a member state changed in this room
         // refresh the conf call notification state
         this._updateConfCallNotification();
diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js
index 0805c0342c..05464b43c9 100644
--- a/src/components/views/rooms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -23,9 +23,9 @@ import SdkConfig from '../../../SdkConfig';
 import dis from '../../../dispatcher';
 import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
 import {isValid3pidInvite} from "../../../RoomInvite";
+import rate_limited_func from "../../../ratelimitedfunc";
 const MatrixClientPeg = require("../../../MatrixClientPeg");
 const sdk = require('../../../index');
-const rate_limited_func = require('../../../ratelimitedfunc');
 const CallHandler = require("../../../CallHandler");
 
 const INITIAL_LOAD_NUM_MEMBERS = 30;
@@ -187,7 +187,7 @@ module.exports = createReactClass({
         }
     },
 
-    _updateList: new rate_limited_func(function() {
+    _updateList: rate_limited_func(function() {
         this._updateListNow();
     }, 500),
 
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 80a03e7a73..210c9394dc 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -27,7 +27,7 @@ const MatrixClientPeg = require("../../../MatrixClientPeg");
 const CallHandler = require('../../../CallHandler');
 const dis = require("../../../dispatcher");
 const sdk = require('../../../index');
-const rate_limited_func = require('../../../ratelimitedfunc');
+import rate_limited_func from "../../../ratelimitedfunc";
 import * as Rooms from '../../../Rooms';
 import DMRoomMap from '../../../utils/DMRoomMap';
 const Receipt = require('../../../utils/Receipt');
@@ -384,7 +384,7 @@ module.exports = createReactClass({
         this._delayedRefreshRoomList();
     },
 
-    _delayedRefreshRoomList: new rate_limited_func(function() {
+    _delayedRefreshRoomList: rate_limited_func(function() {
         this.refreshRoomList();
     }, 500),
 

From 20a615396b0a0ad5c0e748c8ee8b935263179a6f Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 12 Dec 2019 19:31:52 -0700
Subject: [PATCH 09/86] Implementation of new potential skinning mechanism
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With a switch to Only One Webpack™ we need a way to help developers generate the component index without a concurrent watch task. The best way to do this is to have developers import their components, but how do they do that when we support skins? The answer in this commit is to change skinning.

Skinning now expects to receive your list of overrides instead of the react-sdk+branded components. For Riot this means we send over *only* the Vector components and not Vector+react-sdk.

Components can then be annotated with the `replaceComponent` decorator to have them be skinnable. The decorator must take a string with the dot path of the component because we can't reliably calculate it ourselves, sadly.

The decorator does a call to `getComponent` which is where the important part of the branded components not including the react-sdk is important: if the branded app includes the react-sdk then the decorator gets executed before the skin has finished loading, leading to all kinds of fun errors. This is also why the skinner lazily loads the react-sdk components to avoid importing them too early, breaking the app.

The decorator will end up receiving null for a component because of the getComponent loop mentioned: the require() call is still in progress when the decorator is called, therefore we can't error out. All usages of getComponent() within the app are safe to not need such an error (the return won't be null, and developers shouldn't use getComponent() after this commit anyways).

The AuthPage, being a prominent component, has been converted to demonstrate this working. Changes to riot-web are required to have this work.

The reskindex script has also been altered to reflect these skinning changes - it no longer should set the react-sdk as a parent. The eventual end goal is to get rid of `getComponent()` entirely as it'll be easily replaced by imports.
---
 .babelrc                                      |  1 +
 .eslintrc.js                                  |  1 +
 package.json                                  |  1 +
 scripts/reskindex.js                          | 15 +----------
 src/Skinner.js                                | 26 +++++++++++++++----
 .../structures/auth/ForgotPassword.js         |  2 +-
 src/components/structures/auth/Login.js       |  2 +-
 .../structures/auth/PostRegistration.js       |  2 +-
 .../structures/auth/Registration.js           |  2 +-
 src/components/structures/auth/SoftLogout.js  |  2 +-
 src/components/views/auth/AuthPage.js         | 16 ++++++------
 src/components/views/auth/Welcome.js          |  2 +-
 src/utils/replaceComponent.ts                 | 22 ++++++++++++++++
 yarn.lock                                     | 16 ++++++++++++
 14 files changed, 77 insertions(+), 33 deletions(-)
 create mode 100644 src/utils/replaceComponent.ts

diff --git a/.babelrc b/.babelrc
index 3710e20a37..29cd99f8c4 100644
--- a/.babelrc
+++ b/.babelrc
@@ -15,6 +15,7 @@
         "@babel/preset-react"
     ],
     "plugins": [
+        ["@babel/plugin-proposal-decorators", { "legacy": true }],
         "@babel/plugin-proposal-numeric-separator",
         "@babel/plugin-proposal-class-properties",
         "@babel/plugin-proposal-object-rest-spread",
diff --git a/.eslintrc.js b/.eslintrc.js
index 81c3752301..0721c1c8d2 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -25,6 +25,7 @@ module.exports = {
     parserOptions: {
         ecmaFeatures: {
             jsx: true,
+            legacyDecorators: true,
         }
     },
     rules: {
diff --git a/package.json b/package.json
index 3b6e571d0c..99e4983d60 100644
--- a/package.json
+++ b/package.json
@@ -113,6 +113,7 @@
     "@babel/cli": "^7.7.5",
     "@babel/core": "^7.7.5",
     "@babel/plugin-proposal-class-properties": "^7.7.4",
+    "@babel/plugin-proposal-decorators": "^7.7.4",
     "@babel/plugin-proposal-numeric-separator": "^7.7.4",
     "@babel/plugin-proposal-object-rest-spread": "^7.7.4",
     "@babel/plugin-transform-flow-comments": "^7.7.4",
diff --git a/scripts/reskindex.js b/scripts/reskindex.js
index 833151a298..3919295078 100755
--- a/scripts/reskindex.js
+++ b/scripts/reskindex.js
@@ -19,7 +19,6 @@ function reskindex() {
     prevFiles = files;
 
     var header = args.h || args.header;
-    var packageJson = JSON.parse(fs.readFileSync('./package.json'));
 
     var strm = fs.createWriteStream(componentIndexTmp);
 
@@ -34,19 +33,7 @@ function reskindex() {
     strm.write(" * so you'd just be trying to swim upstream like a salmon.\n");
     strm.write(" * You are not a salmon.\n");
     strm.write(" */\n\n");
-
-    if (packageJson['matrix-react-parent']) {
-        const parentIndex = packageJson['matrix-react-parent'] +
-              '/lib/component-index';
-        strm.write(
-`let components = require('${parentIndex}').components;
-if (!components) {
-    throw new Error("'${parentIndex}' didn't export components");
-}
-`);
-    } else {
-        strm.write("let components = {};\n");
-    }
+    strm.write("let components = {};\n");
 
     for (var i = 0; i < files.length; ++i) {
         var file = files[i].replace('.js', '');
diff --git a/src/Skinner.js b/src/Skinner.js
index 1fe12f85ab..7235d55937 100644
--- a/src/Skinner.js
+++ b/src/Skinner.js
@@ -28,15 +28,31 @@ class Skinner {
                 " b) A component has called getComponent at the root level",
             );
         }
-        let comp = this.components[name];
-        // XXX: Temporarily also try 'views.' as we're currently
-        // leaving the 'views.' off views.
+
+        const doLookup = (components) => {
+            if (!components) return null;
+            let comp = components[name];
+            // XXX: Temporarily also try 'views.' as we're currently
+            // leaving the 'views.' off views.
+            if (!comp) {
+                comp = components['views.' + name];
+            }
+            return comp;
+        };
+
+        // Check the skin first
+        let comp = doLookup(this.components);
+
+        // If that failed, check against our own components
         if (!comp) {
-            comp = this.components['views.'+name];
+            // Lazily load our own components because they might end up calling .getComponent()
+            comp = doLookup(require("./component-index").components);
         }
 
+        // Just return nothing instead of erroring - the consumer should be smart enough to
+        // handle this at this point.
         if (!comp) {
-            throw new Error("No such component: "+name);
+            return null;
         }
 
         // components have to be functions.
diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js
index 6f68293caa..ada7d4449b 100644
--- a/src/components/structures/auth/ForgotPassword.js
+++ b/src/components/structures/auth/ForgotPassword.js
@@ -26,6 +26,7 @@ import SdkConfig from "../../../SdkConfig";
 import PasswordReset from "../../../PasswordReset";
 import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import classNames from 'classnames';
+import AuthPage from "../../views/auth/AuthPage";
 
 // Phases
 // Show controls to configure server details
@@ -367,7 +368,6 @@ module.exports = createReactClass({
     },
 
     render: function() {
-        const AuthPage = sdk.getComponent("auth.AuthPage");
         const AuthHeader = sdk.getComponent("auth.AuthHeader");
         const AuthBody = sdk.getComponent("auth.AuthBody");
 
diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js
index b2e9d3e7cd..ade417d156 100644
--- a/src/components/structures/auth/Login.js
+++ b/src/components/structures/auth/Login.js
@@ -26,6 +26,7 @@ import SdkConfig from '../../../SdkConfig';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
 import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import classNames from "classnames";
+import AuthPage from "../../views/auth/AuthPage";
 
 // For validating phone numbers without country codes
 const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
@@ -608,7 +609,6 @@ module.exports = createReactClass({
 
     render: function() {
         const Loader = sdk.getComponent("elements.Spinner");
-        const AuthPage = sdk.getComponent("auth.AuthPage");
         const AuthHeader = sdk.getComponent("auth.AuthHeader");
         const AuthBody = sdk.getComponent("auth.AuthBody");
         const loader = this.isBusy() ? <div className="mx_Login_loader"><Loader /></div> : null;
diff --git a/src/components/structures/auth/PostRegistration.js b/src/components/structures/auth/PostRegistration.js
index 760163585d..a77b4d0d56 100644
--- a/src/components/structures/auth/PostRegistration.js
+++ b/src/components/structures/auth/PostRegistration.js
@@ -20,6 +20,7 @@ import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
+import AuthPage from "../../views/auth/AuthPage";
 
 module.exports = createReactClass({
     displayName: 'PostRegistration',
@@ -59,7 +60,6 @@ module.exports = createReactClass({
     render: function() {
         const ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName');
         const ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
-        const AuthPage = sdk.getComponent('auth.AuthPage');
         const AuthHeader = sdk.getComponent('auth.AuthHeader');
         const AuthBody = sdk.getComponent("auth.AuthBody");
         return (
diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js
index 3578d745f5..69f34f764a 100644
--- a/src/components/structures/auth/Registration.js
+++ b/src/components/structures/auth/Registration.js
@@ -30,6 +30,7 @@ import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDisc
 import classNames from "classnames";
 import * as Lifecycle from '../../../Lifecycle';
 import MatrixClientPeg from "../../../MatrixClientPeg";
+import AuthPage from "../../views/auth/AuthPage";
 
 // Phases
 // Show controls to configure server details
@@ -576,7 +577,6 @@ module.exports = createReactClass({
     render: function() {
         const AuthHeader = sdk.getComponent('auth.AuthHeader');
         const AuthBody = sdk.getComponent("auth.AuthBody");
-        const AuthPage = sdk.getComponent('auth.AuthPage');
         const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
 
         let errorText;
diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js
index 585b4bfe67..da19a852f6 100644
--- a/src/components/structures/auth/SoftLogout.js
+++ b/src/components/structures/auth/SoftLogout.js
@@ -24,6 +24,7 @@ import Modal from '../../../Modal';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import {sendLoginRequest} from "../../../Login";
 import url from 'url';
+import AuthPage from "../../views/auth/AuthPage";
 
 const LOGIN_VIEW = {
     LOADING: 1,
@@ -284,7 +285,6 @@ export default class SoftLogout extends React.Component {
     }
 
     render() {
-        const AuthPage = sdk.getComponent("auth.AuthPage");
         const AuthHeader = sdk.getComponent("auth.AuthHeader");
         const AuthBody = sdk.getComponent("auth.AuthBody");
         const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
diff --git a/src/components/views/auth/AuthPage.js b/src/components/views/auth/AuthPage.js
index 41098c9d6c..8448df9ac8 100644
--- a/src/components/views/auth/AuthPage.js
+++ b/src/components/views/auth/AuthPage.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2019 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,22 +17,21 @@ limitations under the License.
 */
 
 import React from 'react';
-import createReactClass from 'create-react-class';
 import sdk from '../../../index';
+import {replaceComponent} from "../../../utils/replaceComponent";
 
-module.exports = createReactClass({
-    displayName: 'AuthPage',
-
-    render: function() {
+@replaceComponent("views.auth.AuthPage")
+export default class AuthPage extends React.PureComponent {
+    render() {
         const AuthFooter = sdk.getComponent('auth.AuthFooter');
 
         return (
             <div className="mx_AuthPage">
                 <div className="mx_AuthPage_modal">
-                    { this.props.children }
+                    {this.props.children}
                 </div>
                 <AuthFooter />
             </div>
         );
-    },
-});
+    }
+}
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 9cc398329d..a110631033 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -17,10 +17,10 @@ limitations under the License.
 import React from 'react';
 import sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
+import AuthPage from "./AuthPage";
 
 export default class Welcome extends React.PureComponent {
     render() {
-        const AuthPage = sdk.getComponent("auth.AuthPage");
         const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
         const LanguageSelector = sdk.getComponent('auth.LanguageSelector');
 
diff --git a/src/utils/replaceComponent.ts b/src/utils/replaceComponent.ts
new file mode 100644
index 0000000000..1775c42294
--- /dev/null
+++ b/src/utils/replaceComponent.ts
@@ -0,0 +1,22 @@
+/*
+Copyright 2019 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import sdk from '../index';
+
+export function replaceComponent(name: string, origComponent: React.Component) {
+    return () => sdk.getComponent(name) || origComponent;
+}
diff --git a/yarn.lock b/yarn.lock
index 6c05ab5933..4e1be061bc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -303,6 +303,15 @@
     "@babel/helper-create-class-features-plugin" "^7.7.4"
     "@babel/helper-plugin-utils" "^7.0.0"
 
+"@babel/plugin-proposal-decorators@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.7.4.tgz#58c1e21d21ea12f9f5f0a757e46e687b94a7ab2b"
+  integrity sha512-GftcVDcLCwVdzKmwOBDjATd548+IE+mBo7ttgatqNDR7VG7GqIuZPtRWlMLHbhTXhcnFZiGER8iIYl1n/imtsg==
+  dependencies:
+    "@babel/helper-create-class-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-decorators" "^7.7.4"
+
 "@babel/plugin-proposal-dynamic-import@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d"
@@ -358,6 +367,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
+"@babel/plugin-syntax-decorators@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.7.4.tgz#3c91cfee2a111663ff3ac21b851140f5a52a4e0b"
+  integrity sha512-0oNLWNH4k5ZbBVfAwiTU53rKFWIeTh6ZlaWOXWJc4ywxs0tjz5fc3uZ6jKAnZSxN98eXVgg7bJIuzjX+3SXY+A==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
 "@babel/plugin-syntax-dynamic-import@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec"

From 18f81d80dbab2ac1b9bac9f8c1e2177e669c19b4 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 13 Dec 2019 13:43:48 +0000
Subject: [PATCH 10/86] Initial jest stuff. Blocked on Babel 7

---
 package.json                                  |    6 +-
 test/components/structures/GroupView-test.js  |    2 -
 .../structures/MessagePanel-test.js           |    1 -
 test/components/structures/auth/Login-test.js |    1 -
 .../structures/auth/Registration-test.js      |    1 -
 .../dialogs/InteractiveAuthDialog-test.js     |    1 -
 .../elements/MemberEventListSummary-test.js   |    1 -
 .../views/groups/GroupMemberList-test.js      |    2 -
 .../components/views/rooms/MemberList-test.js |    1 -
 .../views/rooms/MessageComposerInput-test.js  |    1 -
 test/components/views/rooms/RoomList-test.js  |    1 -
 .../views/rooms/RoomSettings-test.js          |    1 -
 test/i18n-test/languageHandler-test.js        |    1 -
 test/notifications/ContentRules-test.js       |    4 -
 test/stores/RoomViewStore-test.js             |    1 -
 test/test-utils.js                            |   20 -
 test/utils/MegolmExportEncryption-test.js     |    4 -
 test/utils/permalinks/Permalinks-test.js      |    1 -
 yarn.lock                                     | 1171 ++++++++++++++++-
 19 files changed, 1144 insertions(+), 77 deletions(-)

diff --git a/package.json b/package.json
index 2f35ab7750..e3af86b488 100644
--- a/package.json
+++ b/package.json
@@ -53,8 +53,7 @@
     "stylelint": "stylelint 'res/css/**/*.scss'",
     "clean": "rimraf lib",
     "prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt",
-    "test": "karma start --single-run=true --browsers VectorChromeHeadless",
-    "test-multi": "karma start",
+    "test": "jest --testMatch **/*-test.js",
     "e2etests": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
   },
   "dependencies": {
@@ -118,6 +117,7 @@
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "^10.0.1",
+    "babel-jest": "^23.6.0",
     "babel-loader": "^7.1.5",
     "babel-plugin-add-module-exports": "^0.2.1",
     "babel-plugin-transform-builtin-extend": "^1.1.2",
@@ -142,7 +142,7 @@
     "expect": "^24.1.0",
     "file-loader": "^3.0.1",
     "flow-parser": "^0.57.3",
-    "jest-mock": "^23.2.0",
+    "jest": "^23.2.0",
     "karma": "^4.0.1",
     "karma-chrome-launcher": "^2.2.0",
     "karma-cli": "^1.0.1",
diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index b0768d3911..1319e312fb 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -61,8 +61,6 @@ describe('GroupView', function() {
     };
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
-
         httpBackend = new MockHttpBackend();
 
         Matrix.request(httpBackend.requestFn);
diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js
index 7c52512bc2..cd0a0bfcd7 100644
--- a/test/components/structures/MessagePanel-test.js
+++ b/test/components/structures/MessagePanel-test.js
@@ -75,7 +75,6 @@ describe('MessagePanel', function() {
     let sandbox = null;
 
     beforeEach(function() {
-        test_utils.beforeEach(this);
         sandbox = test_utils.stubClient();
         client = MatrixClientPeg.get();
         client.credentials = {userId: '@me:here'};
diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js
index 6a7982dd47..7a4041f0bc 100644
--- a/test/components/structures/auth/Login-test.js
+++ b/test/components/structures/auth/Login-test.js
@@ -32,7 +32,6 @@ describe('Login', function() {
     let parentDiv;
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
         parentDiv = document.createElement('div');
         document.body.appendChild(parentDiv);
     });
diff --git a/test/components/structures/auth/Registration-test.js b/test/components/structures/auth/Registration-test.js
index 9c125adacc..0ed304f2df 100644
--- a/test/components/structures/auth/Registration-test.js
+++ b/test/components/structures/auth/Registration-test.js
@@ -32,7 +32,6 @@ describe('Registration', function() {
     let parentDiv;
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
         parentDiv = document.createElement('div');
         document.body.appendChild(parentDiv);
     });
diff --git a/test/components/views/dialogs/InteractiveAuthDialog-test.js b/test/components/views/dialogs/InteractiveAuthDialog-test.js
index 5f90e0f21c..5ceba1037b 100644
--- a/test/components/views/dialogs/InteractiveAuthDialog-test.js
+++ b/test/components/views/dialogs/InteractiveAuthDialog-test.js
@@ -36,7 +36,6 @@ describe('InteractiveAuthDialog', function() {
     let sandbox;
 
     beforeEach(function() {
-        test_utils.beforeEach(this);
         sandbox = test_utils.stubClient(sandbox);
         parentDiv = document.createElement('div');
         document.body.appendChild(parentDiv);
diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js
index a31cbdebb5..ab69ae10be 100644
--- a/test/components/views/elements/MemberEventListSummary-test.js
+++ b/test/components/views/elements/MemberEventListSummary-test.js
@@ -88,7 +88,6 @@ describe('MemberEventListSummary', function() {
     };
 
     beforeEach(function(done) {
-        testUtils.beforeEach(this);
         sandbox = testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index 3922610644..6ebdbbd320 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -70,8 +70,6 @@ describe("GroupMemberList", function() {
     };
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
-
         httpBackend = new MockHttpBackend();
 
         Matrix.request(httpBackend.requestFn);
diff --git a/test/components/views/rooms/MemberList-test.js b/test/components/views/rooms/MemberList-test.js
index 9a1439c2f7..2a275e1895 100644
--- a/test/components/views/rooms/MemberList-test.js
+++ b/test/components/views/rooms/MemberList-test.js
@@ -38,7 +38,6 @@ describe('MemberList', () => {
     let defaultUsers = [];
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
         sandbox = TestUtils.stubClient(sandbox);
         client = MatrixClientPeg.get();
         client.hasLazyLoadMembersEnabled = () => false;
diff --git a/test/components/views/rooms/MessageComposerInput-test.js b/test/components/views/rooms/MessageComposerInput-test.js
index 60380eecd2..687bbac926 100644
--- a/test/components/views/rooms/MessageComposerInput-test.js
+++ b/test/components/views/rooms/MessageComposerInput-test.js
@@ -29,7 +29,6 @@ xdescribe('MessageComposerInput', () => {
         room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
 
     beforeEach(function() {
-        testUtils.beforeEach(this);
         sandbox = testUtils.stubClient(sandbox);
         client = MatrixClientPeg.get();
         client.credentials = {userId: '@me:domain.com'};
diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js
index 68168fcf29..cea2105480 100644
--- a/test/components/views/rooms/RoomList-test.js
+++ b/test/components/views/rooms/RoomList-test.js
@@ -45,7 +45,6 @@ describe('RoomList', () => {
     let myOtherMember;
 
     beforeEach(function() {
-        TestUtils.beforeEach(this);
         sandbox = TestUtils.stubClient(sandbox);
         client = MatrixClientPeg.get();
         client.credentials = {userId: myUserId};
diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js
index 1c0bfd95dc..2608eb488a 100644
--- a/test/components/views/rooms/RoomSettings-test.js
+++ b/test/components/views/rooms/RoomSettings-test.js
@@ -36,7 +36,6 @@
 //     }
 //
 //     beforeEach(function(done) {
-//         testUtils.beforeEach(this);
 //         sandbox = testUtils.stubClient();
 //         client = MatrixClientPeg.get();
 //         client.credentials = {userId: '@me:domain.com'};
diff --git a/test/i18n-test/languageHandler-test.js b/test/i18n-test/languageHandler-test.js
index 8f21638703..244fe99000 100644
--- a/test/i18n-test/languageHandler-test.js
+++ b/test/i18n-test/languageHandler-test.js
@@ -8,7 +8,6 @@ describe('languageHandler', function() {
     let sandbox;
 
     beforeEach(function(done) {
-        testUtils.beforeEach(this);
         sandbox = testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
diff --git a/test/notifications/ContentRules-test.js b/test/notifications/ContentRules-test.js
index b58667fee9..3bf0a0426d 100644
--- a/test/notifications/ContentRules-test.js
+++ b/test/notifications/ContentRules-test.js
@@ -58,10 +58,6 @@ var USERNAME_RULE = {
 
 
 describe("ContentRules", function() {
-    beforeEach(function() {
-        test_utils.beforeEach(this);
-    });
-
     describe("parseContentRules", function() {
         it("should handle there being no keyword rules", function() {
             var rules = { 'global': { 'content': [
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index 77dfb37b0a..3762125cd9 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -13,7 +13,6 @@ describe('RoomViewStore', function() {
     let sandbox;
 
     beforeEach(function() {
-        testUtils.beforeEach(this);
         sandbox = testUtils.stubClient();
         peg.get().credentials = { userId: "@test:example.com" };
 
diff --git a/test/test-utils.js b/test/test-utils.js
index 64704fc610..9e8768ae71 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -11,26 +11,6 @@ import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils";
 import ShallowRenderer from 'react-test-renderer/shallow';
 const MatrixEvent = jssdk.MatrixEvent;
 
-/**
- * Perform common actions before each test case, e.g. printing the test case
- * name to stdout.
- * @param {Mocha.Context} context  The test context
- */
-export function beforeEach(context) {
-    const desc = context.currentTest.fullTitle();
-
-    console.log();
-
-    // this puts a mark in the chrome devtools timeline, which can help
-    // figure out what's been going on.
-    if (console.timeStamp) {
-        console.timeStamp(desc);
-    }
-
-    console.log(desc);
-    console.log(new Array(1 + desc.length).join("="));
-}
-
 export function getRenderer() {
     // Old: ReactTestUtils.createRenderer();
     return new ShallowRenderer();
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index fbd945ced6..b411cf3a56 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -74,10 +74,6 @@ describe('MegolmExportEncryption', function() {
         }
     });
 
-    beforeEach(function() {
-        testUtils.beforeEach(this);
-    });
-
     describe('decrypt', function() {
         it('should handle missing header', function() {
             const input=stringToArray(`-----`);
diff --git a/test/utils/permalinks/Permalinks-test.js b/test/utils/permalinks/Permalinks-test.js
index 32a42a7728..2f58afc380 100644
--- a/test/utils/permalinks/Permalinks-test.js
+++ b/test/utils/permalinks/Permalinks-test.js
@@ -69,7 +69,6 @@ describe('Permalinks', function() {
     let sandbox;
 
     beforeEach(function() {
-        testUtils.beforeEach(this);
         sandbox = testUtils.stubClient();
         peg.get().credentials = { userId: "@test:example.com" };
     });
diff --git a/yarn.lock b/yarn.lock
index 85deedbfec..a84fe7b76f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,7 +2,7 @@
 # yarn lockfile v1
 
 
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35", "@babel/code-frame@^7.5.5":
   version "7.5.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
   integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
@@ -475,6 +475,11 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
+abab@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
+  integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
+
 abbrev@1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -488,12 +493,30 @@ accepts@~1.3.4:
     mime-types "~2.1.24"
     negotiator "0.6.2"
 
+acorn-globals@^4.1.0:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
+  integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
+  dependencies:
+    acorn "^6.0.1"
+    acorn-walk "^6.0.1"
+
 acorn-jsx@^5.0.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
   integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
 
-acorn@^6.0.7, acorn@^6.2.1:
+acorn-walk@^6.0.1:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
+  integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+
+acorn@^5.5.3:
+  version "5.7.3"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
+  integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
+
+acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.1:
   version "6.4.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
   integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==
@@ -554,7 +577,7 @@ ansi-colors@^3.0.0:
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
   integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
 
-ansi-escapes@^3.2.0:
+ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
   integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
@@ -610,6 +633,13 @@ anymatch@~3.1.1:
     normalize-path "^3.0.0"
     picomatch "^2.0.4"
 
+append-transform@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+  integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
+  dependencies:
+    default-require-extensions "^1.0.0"
+
 aproba@^1.0.3, aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -652,6 +682,11 @@ arr-union@^3.1.0:
   resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
 
+array-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+  integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
+
 array-find-index@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
@@ -756,7 +791,7 @@ async-limiter@~1.0.0:
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
   integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
 
-async@^2.5.0, async@^2.6.2:
+async@^2.1.4, async@^2.5.0, async@^2.6.2:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
   integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
@@ -827,7 +862,7 @@ babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
-babel-core@^6.26.0, babel-core@^6.26.3:
+babel-core@^6.0.0, babel-core@^6.26.0, babel-core@^6.26.3:
   version "6.26.3"
   resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
   integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
@@ -864,7 +899,7 @@ babel-eslint@^10.0.1:
     eslint-visitor-keys "^1.0.0"
     resolve "^1.12.0"
 
-babel-generator@^6.26.0:
+babel-generator@^6.18.0, babel-generator@^6.26.0:
   version "6.26.1"
   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
   integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
@@ -1000,6 +1035,14 @@ babel-helpers@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
+babel-jest@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
+  integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
+  dependencies:
+    babel-plugin-istanbul "^4.1.6"
+    babel-preset-jest "^23.2.0"
+
 babel-loader@^7.1.5:
   version "7.1.5"
   resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
@@ -1028,6 +1071,21 @@ babel-plugin-check-es2015-constants@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
+babel-plugin-istanbul@^4.1.6:
+  version "4.1.6"
+  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
+  integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
+  dependencies:
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+    find-up "^2.1.0"
+    istanbul-lib-instrument "^1.10.1"
+    test-exclude "^4.2.1"
+
+babel-plugin-jest-hoist@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
+  integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
+
 babel-plugin-syntax-async-functions@^6.8.0:
   version "6.13.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@@ -1058,7 +1116,7 @@ babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
   integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
 
-babel-plugin-syntax-object-rest-spread@^6.8.0:
+babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0:
   version "6.13.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
   integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
@@ -1425,6 +1483,14 @@ babel-preset-flow@^6.23.0:
   dependencies:
     babel-plugin-transform-flow-strip-types "^6.22.0"
 
+babel-preset-jest@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
+  integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
+  dependencies:
+    babel-plugin-jest-hoist "^23.2.0"
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+
 babel-preset-react@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
@@ -1458,7 +1524,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtim
     core-js "^2.4.0"
     regenerator-runtime "^0.11.0"
 
-babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
   integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
@@ -1469,7 +1535,7 @@ babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
     babylon "^6.18.0"
     lodash "^4.17.4"
 
-babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
   integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
@@ -1484,7 +1550,7 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0:
     invariant "^2.2.2"
     lodash "^4.17.4"
 
-babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
   integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
@@ -1664,11 +1730,23 @@ browser-encrypt-attachment@^0.3.0:
   resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c"
   integrity sha1-IFqUyq3w3H6BQTlBgS9lW9GQ/xw=
 
+browser-process-hrtime@^0.1.2:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
+  integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==
+
 browser-request@^0.3.3:
   version "0.3.3"
   resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17"
   integrity sha1-ns5bWsqJopkyJC4Yv5M975h2zBc=
 
+browser-resolve@^1.11.3:
+  version "1.11.3"
+  resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
+  integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
+  dependencies:
+    resolve "1.1.7"
+
 browser-stdout@1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
@@ -1749,6 +1827,13 @@ bs58@^4.0.1:
   dependencies:
     base-x "^3.0.2"
 
+bser@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+  integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+  dependencies:
+    node-int64 "^0.4.0"
+
 buffer-alloc-unsafe@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
@@ -1890,6 +1975,13 @@ caniuse-lite@^1.0.30001012:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0"
   integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==
 
+capture-exit@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
+  integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
+  dependencies:
+    rsvp "^3.3.3"
+
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -2012,6 +2104,11 @@ chrome-trace-event@^1.0.2:
   dependencies:
     tslib "^1.9.0"
 
+ci-info@^1.5.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
 cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -2082,6 +2179,11 @@ clone-regexp@^1.0.0:
     is-regexp "^1.0.0"
     is-supported-regexp-flag "^1.0.0"
 
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+  integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
+
 code-point-at@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
@@ -2129,7 +2231,7 @@ commander@2.15.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
   integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
 
-commander@^2.11.0, commander@^2.20.0:
+commander@^2.11.0, commander@^2.20.0, commander@~2.20.3:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -2229,7 +2331,7 @@ content-type@^1.0.2, content-type@~1.0.4:
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
-convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
+convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
   integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@@ -2372,6 +2474,18 @@ cssesc@^3.0.0:
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
   integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
 
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+  version "0.3.8"
+  resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+  integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
+  integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
+  dependencies:
+    cssom "0.3.x"
+
 currently-unhandled@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -2396,6 +2510,15 @@ dashdash@^1.12.0:
   dependencies:
     assert-plus "^1.0.0"
 
+data-urls@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
+  integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
+  dependencies:
+    abab "^2.0.0"
+    whatwg-mimetype "^2.2.0"
+    whatwg-url "^7.0.0"
+
 date-fns@^1.30.1:
   version "1.30.1"
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
@@ -2447,7 +2570,7 @@ decamelize-keys@^1.0.0:
     decamelize "^1.1.0"
     map-obj "^1.0.0"
 
-decamelize@^1.1.0, decamelize@^1.2.0:
+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -2467,6 +2590,13 @@ deep-is@~0.1.3:
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 
+default-require-extensions@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+  integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
+  dependencies:
+    strip-bom "^2.0.0"
+
 define-properties@^1.1.2, define-properties@^1.1.3, define-properties@~1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2536,6 +2666,11 @@ detect-libc@^1.0.2:
   resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
   integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
 
+detect-newline@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+  integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
+
 di@^0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -2559,7 +2694,7 @@ diff-sequences@^24.9.0:
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
   integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
 
-diff@3.5.0, diff@^3.5.0:
+diff@3.5.0, diff@^3.2.0, diff@^3.5.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
@@ -2639,6 +2774,13 @@ domelementtype@^2.0.1:
   resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
   integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
 
+domexception@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
+  integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
+  dependencies:
+    webidl-conversions "^4.0.2"
+
 domhandler@^2.3.0:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
@@ -2831,7 +2973,7 @@ errno@^0.1.3, errno@~0.1.7:
   dependencies:
     prr "~1.0.1"
 
-error-ex@^1.3.1:
+error-ex@^1.2.0, error-ex@^1.3.1:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
   integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
@@ -2854,6 +2996,23 @@ es-abstract@^1.12.0, es-abstract@^1.15.0, es-abstract@^1.16.2, es-abstract@^1.7.
     string.prototype.trimleft "^2.1.0"
     string.prototype.trimright "^2.1.0"
 
+es-abstract@^1.17.0-next.1:
+  version "1.17.0-next.1"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172"
+  integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==
+  dependencies:
+    es-to-primitive "^1.2.1"
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-symbols "^1.0.1"
+    is-callable "^1.1.4"
+    is-regex "^1.0.4"
+    object-inspect "^1.7.0"
+    object-keys "^1.1.1"
+    object.assign "^4.1.0"
+    string.prototype.trimleft "^2.1.0"
+    string.prototype.trimright "^2.1.0"
+
 es-get-iterator@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.0.1.tgz#ebc4d3bbc2d59dd95a0ecef441ca2dbce7d9e2cd"
@@ -2898,6 +3057,18 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
 
+escodegen@^1.9.1:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
+  integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==
+  dependencies:
+    esprima "^3.1.3"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    optionator "^0.8.1"
+  optionalDependencies:
+    source-map "~0.6.1"
+
 eslint-config-google@^0.7.1:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.7.1.tgz#5598f8498e9e078420f34b80495b8d959f651fb2"
@@ -3034,6 +3205,11 @@ espree@^5.0.1:
     acorn-jsx "^5.0.0"
     eslint-visitor-keys "^1.0.0"
 
+esprima@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+  integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
+
 esprima@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@@ -3058,7 +3234,7 @@ esrever@^0.2.0:
   resolved "https://registry.yarnpkg.com/esrever/-/esrever-0.2.0.tgz#96e9d28f4f1b1a76784cd5d490eaae010e7407b8"
   integrity sha1-lunSj08bGnZ4TNXUkOquAQ50B7g=
 
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
   integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
@@ -3103,6 +3279,13 @@ except@^0.1.3:
   dependencies:
     indexof "0.0.1"
 
+exec-sh@^0.2.0:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
+  integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
+  dependencies:
+    merge "^1.2.0"
+
 execa@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
@@ -3123,6 +3306,11 @@ execall@^1.0.0:
   dependencies:
     clone-regexp "^1.0.0"
 
+exit@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+  integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+
 expand-brackets@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -3170,6 +3358,18 @@ expect@^1.20.2:
     object-keys "^1.0.9"
     tmatch "^2.0.1"
 
+expect@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
+  integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
+  dependencies:
+    ansi-styles "^3.2.0"
+    jest-diff "^23.6.0"
+    jest-get-type "^22.1.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+
 expect@^24.1.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca"
@@ -3269,6 +3469,13 @@ fast-levenshtein@~2.0.6:
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 
+fb-watchman@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
+  integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==
+  dependencies:
+    bser "2.1.1"
+
 fbemitter@^2.0.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865"
@@ -3342,6 +3549,14 @@ filename-regex@^2.0.0:
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
   integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
 
+fileset@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
+  dependencies:
+    glob "^7.0.3"
+    minimatch "^3.0.3"
+
 filesize@3.5.6:
   version "3.5.6"
   resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a"
@@ -3414,6 +3629,14 @@ find-up@4.1.0:
     locate-path "^5.0.0"
     path-exists "^4.0.0"
 
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
 find-up@^2.0.0, find-up@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
@@ -3597,6 +3820,14 @@ fsevents@^1.0.0, fsevents@^1.2.7:
     nan "^2.12.1"
     node-pre-gyp "^0.12.0"
 
+fsevents@^1.2.3:
+  version "1.2.10"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.10.tgz#47252793be8a625a5f96dfaa1c88547f4b20595a"
+  integrity sha512-Dw5DScF/8AWhWzWRbnQrFJfeR/TOJZjRr9Du9kfmd8t234ICcVeDBlauFl/jVcE5ZewhlPoCFvIqp0SE3kAVxA==
+  dependencies:
+    nan "^2.12.1"
+    node-pre-gyp "^0.12.0"
+
 fsevents@~2.1.1:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
@@ -3754,7 +3985,7 @@ glob@^5.0.14:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.1.6"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
   integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -3848,6 +4079,22 @@ growl@1.10.5:
   resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
   integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
 
+growly@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+  integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
+
+handlebars@^4.0.3:
+  version "4.5.3"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
+  integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
+  dependencies:
+    neo-async "^2.6.0"
+    optimist "^0.6.1"
+    source-map "^0.6.1"
+  optionalDependencies:
+    uglify-js "^3.1.4"
+
 har-schema@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -3880,6 +4127,11 @@ has-cors@1.1.0:
   resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
   integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
 
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+
 has-flag@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
@@ -4007,6 +4259,13 @@ hosted-git-info@^2.1.4:
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
   integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
 
+html-encoding-sniffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
+  integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
+  dependencies:
+    whatwg-encoding "^1.0.1"
+
 html-tags@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
@@ -4154,6 +4413,14 @@ import-local@2.0.0:
     pkg-dir "^3.0.0"
     resolve-cwd "^2.0.0"
 
+import-local@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+  integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
+  dependencies:
+    pkg-dir "^2.0.0"
+    resolve-cwd "^2.0.0"
+
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -4341,6 +4608,13 @@ is-callable@^1.0.4, is-callable@^1.1.4:
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
   integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
 
+is-ci@^1.0.10:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+  integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+  dependencies:
+    ci-info "^1.5.0"
+
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -4470,6 +4744,11 @@ is-fullwidth-code-point@^3.0.0:
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
   integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
 
+is-generator-fn@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
+  integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
+
 is-generator-function@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
@@ -4628,6 +4907,11 @@ is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+
 is-weakmap@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.0.tgz#88bd0b8ec3a5724477637d58ed96cb00552593fd"
@@ -4725,6 +5009,155 @@ isstream@~0.1.2:
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
+istanbul-api@^1.3.1:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
+  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
+  dependencies:
+    async "^2.1.4"
+    fileset "^2.0.2"
+    istanbul-lib-coverage "^1.2.1"
+    istanbul-lib-hook "^1.2.2"
+    istanbul-lib-instrument "^1.10.2"
+    istanbul-lib-report "^1.1.5"
+    istanbul-lib-source-maps "^1.2.6"
+    istanbul-reports "^1.5.1"
+    js-yaml "^3.7.0"
+    mkdirp "^0.5.1"
+    once "^1.4.0"
+
+istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
+  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
+
+istanbul-lib-hook@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
+  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+  dependencies:
+    append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
+  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+  dependencies:
+    babel-generator "^6.18.0"
+    babel-template "^6.16.0"
+    babel-traverse "^6.18.0"
+    babel-types "^6.18.0"
+    babylon "^6.18.0"
+    istanbul-lib-coverage "^1.2.1"
+    semver "^5.3.0"
+
+istanbul-lib-report@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
+  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+  dependencies:
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    path-parse "^1.0.5"
+    supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
+  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+  dependencies:
+    debug "^3.1.0"
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    rimraf "^2.6.1"
+    source-map "^0.5.3"
+
+istanbul-reports@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
+  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
+  dependencies:
+    handlebars "^4.0.3"
+
+jest-changed-files@^23.4.2:
+  version "23.4.2"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
+  integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+  dependencies:
+    throat "^4.0.0"
+
+jest-cli@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
+  integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    glob "^7.1.2"
+    graceful-fs "^4.1.11"
+    import-local "^1.0.0"
+    is-ci "^1.0.10"
+    istanbul-api "^1.3.1"
+    istanbul-lib-coverage "^1.2.0"
+    istanbul-lib-instrument "^1.10.1"
+    istanbul-lib-source-maps "^1.2.4"
+    jest-changed-files "^23.4.2"
+    jest-config "^23.6.0"
+    jest-environment-jsdom "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve-dependencies "^23.6.0"
+    jest-runner "^23.6.0"
+    jest-runtime "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    jest-watcher "^23.4.0"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    node-notifier "^5.2.1"
+    prompts "^0.1.9"
+    realpath-native "^1.0.0"
+    rimraf "^2.5.4"
+    slash "^1.0.0"
+    string-length "^2.0.0"
+    strip-ansi "^4.0.0"
+    which "^1.2.12"
+    yargs "^11.0.0"
+
+jest-config@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
+  integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-jest "^23.6.0"
+    chalk "^2.0.1"
+    glob "^7.1.1"
+    jest-environment-jsdom "^23.4.0"
+    jest-environment-node "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-jasmine2 "^23.6.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    pretty-format "^23.6.0"
+
+jest-diff@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
+  integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
+  dependencies:
+    chalk "^2.0.1"
+    diff "^3.2.0"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
+
 jest-diff@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
@@ -4735,11 +5168,96 @@ jest-diff@^24.9.0:
     jest-get-type "^24.9.0"
     pretty-format "^24.9.0"
 
+jest-docblock@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
+  integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
+  dependencies:
+    detect-newline "^2.1.0"
+
+jest-each@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
+  integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+  dependencies:
+    chalk "^2.0.1"
+    pretty-format "^23.6.0"
+
+jest-environment-jsdom@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
+  integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
+  dependencies:
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+    jsdom "^11.5.1"
+
+jest-environment-node@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
+  integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
+  dependencies:
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+
+jest-get-type@^22.1.0:
+  version "22.4.3"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
+  integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+
 jest-get-type@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
   integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
 
+jest-haste-map@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
+  integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+  dependencies:
+    fb-watchman "^2.0.0"
+    graceful-fs "^4.1.11"
+    invariant "^2.2.4"
+    jest-docblock "^23.2.0"
+    jest-serializer "^23.0.1"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    sane "^2.0.0"
+
+jest-jasmine2@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
+  integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
+  dependencies:
+    babel-traverse "^6.0.0"
+    chalk "^2.0.1"
+    co "^4.6.0"
+    expect "^23.6.0"
+    is-generator-fn "^1.0.0"
+    jest-diff "^23.6.0"
+    jest-each "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    pretty-format "^23.6.0"
+
+jest-leak-detector@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
+  integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+  dependencies:
+    pretty-format "^23.6.0"
+
+jest-matcher-utils@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
+  integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
+
 jest-matcher-utils@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073"
@@ -4750,6 +5268,17 @@ jest-matcher-utils@^24.9.0:
     jest-get-type "^24.9.0"
     pretty-format "^24.9.0"
 
+jest-message-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
+  integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
+  dependencies:
+    "@babel/code-frame" "^7.0.0-beta.35"
+    chalk "^2.0.1"
+    micromatch "^2.3.11"
+    slash "^1.0.0"
+    stack-utils "^1.0.1"
+
 jest-message-util@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3"
@@ -4769,11 +5298,140 @@ jest-mock@^23.2.0:
   resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
   integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
 
+jest-regex-util@^23.3.0:
+  version "23.3.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
+  integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
+
 jest-regex-util@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636"
   integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==
 
+jest-resolve-dependencies@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
+  integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+  dependencies:
+    jest-regex-util "^23.3.0"
+    jest-snapshot "^23.6.0"
+
+jest-resolve@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
+  integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+  dependencies:
+    browser-resolve "^1.11.3"
+    chalk "^2.0.1"
+    realpath-native "^1.0.0"
+
+jest-runner@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
+  integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+  dependencies:
+    exit "^0.1.2"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-docblock "^23.2.0"
+    jest-haste-map "^23.6.0"
+    jest-jasmine2 "^23.6.0"
+    jest-leak-detector "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-runtime "^23.6.0"
+    jest-util "^23.4.0"
+    jest-worker "^23.2.0"
+    source-map-support "^0.5.6"
+    throat "^4.0.0"
+
+jest-runtime@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
+  integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-plugin-istanbul "^4.1.6"
+    chalk "^2.0.1"
+    convert-source-map "^1.4.0"
+    exit "^0.1.2"
+    fast-json-stable-stringify "^2.0.0"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    realpath-native "^1.0.0"
+    slash "^1.0.0"
+    strip-bom "3.0.0"
+    write-file-atomic "^2.1.0"
+    yargs "^11.0.0"
+
+jest-serializer@^23.0.1:
+  version "23.0.1"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
+  integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
+
+jest-snapshot@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
+  integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
+  dependencies:
+    babel-types "^6.0.0"
+    chalk "^2.0.1"
+    jest-diff "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-resolve "^23.6.0"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    pretty-format "^23.6.0"
+    semver "^5.5.0"
+
+jest-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
+  integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
+  dependencies:
+    callsites "^2.0.0"
+    chalk "^2.0.1"
+    graceful-fs "^4.1.11"
+    is-ci "^1.0.10"
+    jest-message-util "^23.4.0"
+    mkdirp "^0.5.1"
+    slash "^1.0.0"
+    source-map "^0.6.0"
+
+jest-validate@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
+  integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    leven "^2.1.0"
+    pretty-format "^23.6.0"
+
+jest-watcher@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
+  integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    string-length "^2.0.0"
+
+jest-worker@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
+  integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
+  dependencies:
+    merge-stream "^1.0.1"
+
 jest-worker@^24.6.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
@@ -4782,6 +5440,14 @@ jest-worker@^24.6.0:
     merge-stream "^2.0.0"
     supports-color "^6.1.0"
 
+jest@^23.2.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
+  integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+  dependencies:
+    import-local "^1.0.0"
+    jest-cli "^23.6.0"
+
 jquery@^3.3.1:
   version "3.4.1"
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
@@ -4797,7 +5463,7 @@ js-tokens@^3.0.2:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
   integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
 
-js-yaml@^3.13.0, js-yaml@^3.13.1:
+js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.7.0:
   version "3.13.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
   integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@@ -4810,6 +5476,38 @@ jsbn@~0.1.0:
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
+jsdom@^11.5.1:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
+  integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
+  dependencies:
+    abab "^2.0.0"
+    acorn "^5.5.3"
+    acorn-globals "^4.1.0"
+    array-equal "^1.0.0"
+    cssom ">= 0.3.2 < 0.4.0"
+    cssstyle "^1.0.0"
+    data-urls "^1.0.0"
+    domexception "^1.0.1"
+    escodegen "^1.9.1"
+    html-encoding-sniffer "^1.0.2"
+    left-pad "^1.3.0"
+    nwsapi "^2.0.7"
+    parse5 "4.0.0"
+    pn "^1.1.0"
+    request "^2.87.0"
+    request-promise-native "^1.0.5"
+    sax "^1.2.4"
+    symbol-tree "^3.2.2"
+    tough-cookie "^2.3.4"
+    w3c-hr-time "^1.0.1"
+    webidl-conversions "^4.0.2"
+    whatwg-encoding "^1.0.3"
+    whatwg-mimetype "^2.1.0"
+    whatwg-url "^6.4.1"
+    ws "^5.2.0"
+    xml-name-validator "^3.0.0"
+
 jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
@@ -5015,6 +5713,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
   integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
 
+kleur@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
+  integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+
 known-css-properties@^0.11.0:
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a"
@@ -5027,6 +5730,11 @@ lcid@^2.0.0:
   dependencies:
     invert-kv "^2.0.0"
 
+left-pad@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
+  integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
+
 leven@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -5049,6 +5757,17 @@ linkifyjs@^2.1.6:
     react "^16.4.2"
     react-dom "^16.4.2"
 
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
 load-json-file@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
@@ -5141,6 +5860,11 @@ lodash.mergewith@^4.6.1:
   resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
   integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
 
+lodash.sortby@^4.7.0:
+  version "4.7.0"
+  resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+  integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
+
 lodash.unescape@4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
@@ -5251,6 +5975,13 @@ make-fetch-happen@5.0.0:
     socks-proxy-agent "^4.0.0"
     ssri "^6.0.0"
 
+makeerror@1.0.x:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
+  integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=
+  dependencies:
+    tmpl "1.0.x"
+
 mamacro@^0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
@@ -5407,6 +6138,13 @@ meow@^5.0.0:
     trim-newlines "^2.0.0"
     yargs-parser "^10.0.0"
 
+merge-stream@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+  integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
+  dependencies:
+    readable-stream "^2.0.1"
+
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -5417,7 +6155,12 @@ merge2@^1.2.3:
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
   integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
 
-micromatch@^2.1.5:
+merge@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
+  integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
+
+micromatch@^2.1.5, micromatch@^2.3.11:
   version "2.3.11"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
   integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
@@ -5500,7 +6243,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
 
-"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -5525,7 +6268,7 @@ minimist@1.1.x:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
   integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=
 
-minimist@1.2.0, minimist@^1.2.0, "minimist@~ 1.2.0":
+minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
@@ -5666,7 +6409,7 @@ negotiator@0.6.2:
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
   integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
 
-neo-async@^2.5.0, neo-async@^2.6.1:
+neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
   integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
@@ -5704,6 +6447,11 @@ node-fetch@^1.0.1:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
+node-int64@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+  integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
+
 node-libs-browser@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
@@ -5733,6 +6481,17 @@ node-libs-browser@^2.2.1:
     util "^0.11.0"
     vm-browserify "^1.0.1"
 
+node-notifier@^5.2.1:
+  version "5.4.3"
+  resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50"
+  integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==
+  dependencies:
+    growly "^1.3.0"
+    is-wsl "^1.1.0"
+    semver "^5.5.0"
+    shellwords "^0.1.1"
+    which "^1.3.0"
+
 node-pre-gyp@^0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
@@ -5841,6 +6600,11 @@ number-is-nan@^1.0.0:
   resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
   integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
 
+nwsapi@^2.0.7:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
+  integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
+
 oauth-sign@~0.9.0:
   version "0.9.0"
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
@@ -5912,6 +6676,14 @@ object.fromentries@^2.0.1:
     function-bind "^1.1.1"
     has "^1.0.3"
 
+object.getownpropertydescriptors@^2.0.3:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649"
+  integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==
+  dependencies:
+    define-properties "^1.1.3"
+    es-abstract "^1.17.0-next.1"
+
 object.omit@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@@ -5966,7 +6738,7 @@ optimist@^0.6.1:
     minimist "~0.0.1"
     wordwrap "~0.0.2"
 
-optionator@^0.8.2:
+optionator@^0.8.1, optionator@^0.8.2:
   version "0.8.3"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
   integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -6134,6 +6906,13 @@ parse-glob@^3.0.4:
     is-extglob "^1.0.0"
     is-glob "^2.0.0"
 
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
+  dependencies:
+    error-ex "^1.2.0"
+
 parse-json@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -6147,6 +6926,11 @@ parse-passwd@^1.0.0:
   resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
   integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
 
+parse5@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
+  integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
+
 parseqs@0.0.5:
   version "0.0.5"
   resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
@@ -6181,6 +6965,13 @@ path-dirname@^1.0.0:
   resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
   integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
 
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+  dependencies:
+    pinkie-promise "^2.0.0"
+
 path-exists@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -6206,7 +6997,7 @@ path-key@^2.0.0, path-key@^2.0.1:
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
   integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 
-path-parse@^1.0.6:
+path-parse@^1.0.5, path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
@@ -6218,6 +7009,15 @@ path-to-regexp@^1.7.0:
   dependencies:
     isarray "0.0.1"
 
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
+  dependencies:
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
 path-type@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@@ -6251,6 +7051,11 @@ picomatch@^2.0.4:
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
   integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
 
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+  integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+
 pify@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
@@ -6261,6 +7066,18 @@ pify@^4.0.0, pify@^4.0.1:
   resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+  integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+
 pkg-dir@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -6280,6 +7097,11 @@ pluralizers@^0.1.7:
   resolved "https://registry.yarnpkg.com/pluralizers/-/pluralizers-0.1.7.tgz#8d38dd0a1b660e739b10ab2eab10b684c9d50142"
   integrity sha512-mw6AejUiCaMQ6uPN9ObjJDTnR5AnBSmnHHy3uVTbxrSFSxO5scfwpTs8Dxyb6T2v7GSulhvOq+pm9y+hXUvtOA==
 
+pn@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+  integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+
 png-chunks-extract@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz#fad4a905e66652197351c65e35b92c64311e472d"
@@ -6415,6 +7237,14 @@ preserve@^0.2.0:
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
   integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
 
+pretty-format@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+  dependencies:
+    ansi-regex "^3.0.0"
+    ansi-styles "^3.2.0"
+
 pretty-format@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
@@ -6465,6 +7295,14 @@ promise@^7.0.3, promise@^7.1.1:
   dependencies:
     asap "~2.0.3"
 
+prompts@^0.1.9:
+  version "0.1.14"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
+  integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+  dependencies:
+    kleur "^2.0.1"
+    sisteransi "^0.1.1"
+
 prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@@ -6489,6 +7327,11 @@ psl@^1.1.24:
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.5.0.tgz#47fd1292def7fdb1e138cd78afa8814cebcf7b13"
   integrity sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA==
 
+psl@^1.1.28:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110"
+  integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==
+
 public-encrypt@^4.0.0:
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@@ -6536,7 +7379,7 @@ punycode@^1.2.4, punycode@^1.4.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
   integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
 
-punycode@^2.1.0:
+punycode@^2.1.0, punycode@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@@ -6755,6 +7598,14 @@ react@^16.4.2, react@^16.9.0:
     object-assign "^4.1.1"
     prop-types "^15.6.2"
 
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
 read-pkg-up@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
@@ -6763,6 +7614,15 @@ read-pkg-up@^3.0.0:
     find-up "^2.0.0"
     read-pkg "^3.0.0"
 
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
 read-pkg@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
@@ -6819,6 +7679,13 @@ readdirp@~3.2.0:
   dependencies:
     picomatch "^2.0.4"
 
+realpath-native@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
+  integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
+  dependencies:
+    util.promisify "^1.0.0"
+
 redent@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
@@ -6997,7 +7864,23 @@ replace-ext@1.0.0:
   resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
   integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
 
-request@^2.88.0:
+request-promise-core@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9"
+  integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==
+  dependencies:
+    lodash "^4.17.15"
+
+request-promise-native@^1.0.5:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36"
+  integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==
+  dependencies:
+    request-promise-core "1.1.3"
+    stealthy-require "^1.1.1"
+    tough-cookie "^2.3.3"
+
+request@^2.87.0, request@^2.88.0:
   version "2.88.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
   integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
@@ -7088,6 +7971,11 @@ resolve-url@^0.2.1:
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
+resolve@1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+  integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
+
 resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
@@ -7158,6 +8046,11 @@ rollup-pluginutils@^2.8.1:
   dependencies:
     estree-walker "^0.6.1"
 
+rsvp@^3.3.3:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
+  integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+
 run-async@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
@@ -7206,6 +8099,22 @@ samsam@1.3.0:
   resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
   integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==
 
+sane@^2.0.0:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
+  integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
+  dependencies:
+    anymatch "^2.0.0"
+    capture-exit "^1.2.0"
+    exec-sh "^0.2.0"
+    fb-watchman "^2.0.0"
+    micromatch "^3.1.4"
+    minimist "^1.1.1"
+    walker "~1.0.5"
+    watch "~0.18.0"
+  optionalDependencies:
+    fsevents "^1.2.3"
+
 sanitize-html@^1.18.4:
   version "1.20.1"
   resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.1.tgz#f6effdf55dd398807171215a62bfc21811bacf85"
@@ -7316,6 +8225,11 @@ shebang-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
   integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
 
+shellwords@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
+  integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
+
 signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@@ -7334,6 +8248,11 @@ sinon@^5.0.7:
     supports-color "^5.4.0"
     type-detect "^4.0.8"
 
+sisteransi@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
+  integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
+
 slash@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
@@ -7568,7 +8487,7 @@ source-map-support@^0.4.15:
   dependencies:
     source-map "^0.5.6"
 
-source-map-support@~0.5.12:
+source-map-support@^0.5.6, source-map-support@~0.5.12:
   version "0.5.16"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
   integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
@@ -7581,7 +8500,7 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
-source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -7702,6 +8621,11 @@ static-extend@^0.1.1:
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
 
+stealthy-require@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+  integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
+
 stream-browserify@^2.0.1:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
@@ -7745,6 +8669,14 @@ streamroller@^1.0.6:
     fs-extra "^7.0.1"
     lodash "^4.17.14"
 
+string-length@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
+  integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=
+  dependencies:
+    astral-regex "^1.0.0"
+    strip-ansi "^4.0.0"
+
 string-width@4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff"
@@ -7846,11 +8778,18 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
-strip-bom@^3.0.0:
+strip-bom@3.0.0, strip-bom@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
   integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
 
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+  dependencies:
+    is-utf8 "^0.2.0"
+
 strip-eof@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -7975,6 +8914,13 @@ supports-color@^2.0.0:
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
   integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
 
+supports-color@^3.1.2:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+  dependencies:
+    has-flag "^1.0.0"
+
 supports-color@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
@@ -7999,6 +8945,11 @@ symbol-observable@^1.0.3:
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
   integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
 
+symbol-tree@^3.2.2:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+  integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
 tabbable@^1.0.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.3.tgz#0e4ee376f3631e42d7977a074dbd2b3827843081"
@@ -8056,6 +9007,17 @@ terser@^4.1.0, terser@^4.1.2:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
+test-exclude@^4.2.1:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
+  integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+  dependencies:
+    arrify "^1.0.1"
+    micromatch "^2.3.11"
+    object-assign "^4.1.0"
+    read-pkg-up "^1.0.1"
+    require-main-filename "^1.0.1"
+
 text-encoding-utf-8@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
@@ -8066,6 +9028,11 @@ text-table@0.2.0, text-table@^0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
   integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
 
+throat@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
+  integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
+
 through2@^2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -8098,6 +9065,11 @@ tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
   dependencies:
     os-tmpdir "~1.0.2"
 
+tmpl@1.0.x:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
+  integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
+
 to-array@0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
@@ -8155,6 +9127,14 @@ toidentifier@1.0.0:
   resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
   integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
 
+tough-cookie@^2.3.3, tough-cookie@^2.3.4:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+  integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+  dependencies:
+    psl "^1.1.28"
+    punycode "^2.1.1"
+
 tough-cookie@~2.4.3:
   version "2.4.3"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
@@ -8163,6 +9143,13 @@ tough-cookie@~2.4.3:
     psl "^1.1.24"
     punycode "^1.4.1"
 
+tr46@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+  integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
+  dependencies:
+    punycode "^2.1.0"
+
 tree-kill@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a"
@@ -8257,6 +9244,14 @@ ua-parser-js@^0.7.18:
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
   integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
 
+uglify-js@^3.1.4:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9"
+  integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==
+  dependencies:
+    commander "~2.20.3"
+    source-map "~0.6.1"
+
 ultron@~1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
@@ -8445,6 +9440,14 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
   integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
 
+util.promisify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+  integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
+  dependencies:
+    define-properties "^1.1.2"
+    object.getownpropertydescriptors "^2.0.3"
+
 util@0.10.3:
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
@@ -8543,6 +9546,13 @@ void-elements@^2.0.0:
   resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
   integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
 
+w3c-hr-time@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
+  integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=
+  dependencies:
+    browser-process-hrtime "^0.1.2"
+
 walk@^2.3.9:
   version "2.3.14"
   resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.14.tgz#60ec8631cfd23276ae1e7363ce11d626452e1ef3"
@@ -8550,6 +9560,13 @@ walk@^2.3.9:
   dependencies:
     foreachasync "^3.0.0"
 
+walker@~1.0.5:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
+  integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
+  dependencies:
+    makeerror "1.0.x"
+
 warning@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
@@ -8557,6 +9574,14 @@ warning@^3.0.0:
   dependencies:
     loose-envify "^1.0.0"
 
+watch@~0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
+  integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
+  dependencies:
+    exec-sh "^0.2.0"
+    minimist "^1.2.0"
+
 watchpack@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
@@ -8566,6 +9591,11 @@ watchpack@^1.6.0:
     graceful-fs "^4.1.2"
     neo-async "^2.5.0"
 
+webidl-conversions@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+  integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
 webpack-cli@^3.1.1:
   version "3.3.10"
   resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13"
@@ -8644,6 +9674,13 @@ what-input@^5.2.6:
   resolved "https://registry.yarnpkg.com/what-input/-/what-input-5.2.6.tgz#ac6f003bf8d3592a0031dea7a03565469b00020b"
   integrity sha512-a0BcI5YR7xp87vSzGcbN0IszJKpUQuTmrZaTSQBl7TLDIdKj6rDhluQ7b/7lYGG81gWDvkySsEvwv4BW5an9kg==
 
+whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+  integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+  dependencies:
+    iconv-lite "0.4.24"
+
 whatwg-fetch@>=0.10.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
@@ -8659,6 +9696,29 @@ whatwg-fetch@^1.1.1:
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319"
   integrity sha1-rDydOfMgxtzlM5lp0FTvQ90zMxk=
 
+whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+  integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^6.4.1:
+  version "6.5.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
+  integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
+whatwg-url@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+  integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
 which-boxed-primitive@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1"
@@ -8685,7 +9745,7 @@ which-module@^2.0.0:
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1:
+which@^1.2.1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -8738,6 +9798,15 @@ wrappy@1:
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 
+write-file-atomic@^2.1.0:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+  integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+  dependencies:
+    graceful-fs "^4.1.11"
+    imurmurhash "^0.1.4"
+    signal-exit "^3.0.2"
+
 write@1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
@@ -8745,6 +9814,13 @@ write@1.0.3:
   dependencies:
     mkdirp "^0.5.1"
 
+ws@^5.2.0:
+  version "5.2.2"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
+  integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
+  dependencies:
+    async-limiter "~1.0.0"
+
 ws@~3.3.1:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
@@ -8759,6 +9835,11 @@ x-is-string@^0.1.0:
   resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
   integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
 
+xml-name-validator@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+  integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
 xmlhttprequest-ssl@~1.5.4:
   version "1.5.5"
   resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
@@ -8769,6 +9850,11 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
   integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
 
+y18n@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+  integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
+
 "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@@ -8807,6 +9893,13 @@ yargs-parser@^13.1.0:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
+yargs-parser@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+  integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
+  dependencies:
+    camelcase "^4.1.0"
+
 yargs@13.2.4:
   version "13.2.4"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
@@ -8824,6 +9917,24 @@ yargs@13.2.4:
     y18n "^4.0.0"
     yargs-parser "^13.1.0"
 
+yargs@^11.0.0:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
+  integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^1.1.1"
+    find-up "^2.1.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.1.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^9.0.2"
+
 yargs@^12.0.5:
   version "12.0.5"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"

From ffa2ac172c2d7dabeeb9d94f3c2a67bea04d5c6f Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Sun, 15 Dec 2019 14:09:41 +0000
Subject: [PATCH 11/86] delint

---
 test/components/structures/auth/Login-test.js        | 1 -
 test/components/structures/auth/Registration-test.js | 1 -
 test/utils/MegolmExportEncryption-test.js            | 1 -
 3 files changed, 3 deletions(-)

diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js
index 7a4041f0bc..d06e754e3e 100644
--- a/test/components/structures/auth/Login-test.js
+++ b/test/components/structures/auth/Login-test.js
@@ -21,7 +21,6 @@ import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
 import sdk from 'matrix-react-sdk';
 import SdkConfig from '../../../../src/SdkConfig';
-import * as TestUtils from '../../../test-utils';
 import {mkServerConfig} from "../../../test-utils";
 
 const Login = sdk.getComponent(
diff --git a/test/components/structures/auth/Registration-test.js b/test/components/structures/auth/Registration-test.js
index 0ed304f2df..ad82597f8b 100644
--- a/test/components/structures/auth/Registration-test.js
+++ b/test/components/structures/auth/Registration-test.js
@@ -21,7 +21,6 @@ import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
 import sdk from 'matrix-react-sdk';
 import SdkConfig from '../../../../src/SdkConfig';
-import * as TestUtils from '../../../test-utils';
 import {mkServerConfig} from "../../../test-utils";
 
 const Registration = sdk.getComponent(
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index b411cf3a56..a1dae391e6 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -18,7 +18,6 @@ limitations under the License.
 
 import * as MegolmExportEncryption from '../../src/utils/MegolmExportEncryption';
 
-import * as testUtils from '../test-utils';
 import expect from 'expect';
 
 const TEST_VECTORS=[

From 6ad31fe0232c9471bdf60b7172509e123a46d4cd Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 16 Dec 2019 11:12:48 +0000
Subject: [PATCH 12/86] 30 test failures to go :D

---
 package.json                                  |   3 +-
 test/DecryptionFailureTracker-test.js         |   2 -
 test/PhasedRollOut-test.js                    |   1 -
 test/ScalarAuthClient-test.js                 |  38 +-
 test/Terms-test.js                            |  95 ++---
 test/UserActivity-test.js                     |   1 -
 test/all-tests.js                             |   7 -
 test/autocomplete/QueryMatcher-test.js        |   2 -
 test/components/structures/GroupView-test.js  |   5 +-
 .../structures/MessagePanel-test.js           |   9 +-
 test/components/structures/auth/Login-test.js |   7 +-
 .../structures/auth/Registration-test.js      |   7 +-
 .../dialogs/InteractiveAuthDialog-test.js     |  16 +-
 .../elements/MemberEventListSummary-test.js   |  11 +-
 .../views/groups/GroupMemberList-test.js      |   5 +-
 .../components/views/rooms/MemberList-test.js |   7 +-
 .../views/rooms/MessageComposerInput-test.js  |  90 ++---
 test/components/views/rooms/RoomList-test.js  |   7 +-
 .../views/rooms/RoomSettings-test.js          | 375 +++++++++---------
 test/editor/caret-test.js                     |   1 -
 test/editor/deserialize-test.js               |   1 -
 test/editor/diff-test.js                      |   1 -
 test/editor/history-test.js                   |   1 -
 test/editor/model-test.js                     |   1 -
 test/editor/position-test.js                  |   1 -
 test/editor/range-test.js                     |   1 -
 test/editor/serialize-test.js                 |   1 -
 test/i18n-test/languageHandler-test.js        |   8 +-
 test/stores/RoomViewStore-test.js             |  11 +-
 test/test-utils.js                            |  76 ++--
 test/utils/MegolmExportEncryption-test.js     |  21 +-
 test/utils/permalinks/Permalinks-test.js      |   9 +-
 yarn.lock                                     | 312 +++------------
 33 files changed, 424 insertions(+), 709 deletions(-)
 delete mode 100644 test/all-tests.js

diff --git a/package.json b/package.json
index e3af86b488..b21b2cedac 100644
--- a/package.json
+++ b/package.json
@@ -139,7 +139,6 @@
     "eslint-plugin-react": "^7.7.0",
     "eslint-plugin-react-hooks": "^2.0.1",
     "estree-walker": "^0.5.0",
-    "expect": "^24.1.0",
     "file-loader": "^3.0.1",
     "flow-parser": "^0.57.3",
     "jest": "^23.2.0",
@@ -158,11 +157,11 @@
     "react-test-renderer": "^16.9.0",
     "require-json": "0.0.1",
     "rimraf": "^2.4.3",
-    "sinon": "^5.0.7",
     "source-map-loader": "^0.2.3",
     "stylelint": "^9.10.1",
     "stylelint-config-standard": "^18.2.0",
     "stylelint-scss": "^3.9.0",
+    "subtle": "^0.1.8",
     "walk": "^2.3.9",
     "webpack": "^4.20.2",
     "webpack-cli": "^3.1.1"
diff --git a/test/DecryptionFailureTracker-test.js b/test/DecryptionFailureTracker-test.js
index baa0545f77..7a6a42ef55 100644
--- a/test/DecryptionFailureTracker-test.js
+++ b/test/DecryptionFailureTracker-test.js
@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-
 import { DecryptionFailure, DecryptionFailureTracker } from '../src/DecryptionFailureTracker';
 
 import { MatrixEvent } from 'matrix-js-sdk';
diff --git a/test/PhasedRollOut-test.js b/test/PhasedRollOut-test.js
index 600b9051f7..f02411d78d 100644
--- a/test/PhasedRollOut-test.js
+++ b/test/PhasedRollOut-test.js
@@ -11,7 +11,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import {phasedRollOutExpiredForUser} from '../src/PhasedRollOut';
 
 const OFFSET = 6000000;
diff --git a/test/ScalarAuthClient-test.js b/test/ScalarAuthClient-test.js
index 7e944189a6..28ca914f00 100644
--- a/test/ScalarAuthClient-test.js
+++ b/test/ScalarAuthClient-test.js
@@ -14,43 +14,41 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-
-import sinon from 'sinon';
-
 import ScalarAuthClient from '../src/ScalarAuthClient';
 import MatrixClientPeg from '../src/MatrixClientPeg';
 import { stubClient } from './test-utils';
 
 describe('ScalarAuthClient', function() {
-    let clientSandbox;
-
     beforeEach(function() {
-        sinon.stub(window.localStorage, 'getItem').withArgs('mx_scalar_token').returns('brokentoken');
-        clientSandbox = stubClient();
-    });
-
-    afterEach(function() {
-        clientSandbox.restore();
-        sinon.restore();
+        window.localStorage.getItem = jest.fn((arg) => {
+            if (arg === "mx_scalar_token") return "brokentoken";
+        });
+        stubClient();
     });
 
     it('should request a new token if the old one fails', async function() {
         const sac = new ScalarAuthClient();
 
-        sac._getAccountName = sinon.stub();
-        sac._getAccountName.withArgs('brokentoken').rejects({
-            message: "Invalid token",
+        sac._getAccountName = jest.fn((arg) => {
+            switch (arg) {
+                case "brokentoken":
+                    return Promise.reject({
+                        message: "Invalid token",
+                    });
+                case "wokentoken":
+                    return Promise.resolve(MatrixClientPeg.get().getUserId());
+            }
         });
-        sac._getAccountName.withArgs('wokentoken').resolves(MatrixClientPeg.get().getUserId());
 
-        MatrixClientPeg.get().getOpenIdToken = sinon.stub().resolves('this is your openid token');
+        MatrixClientPeg.get().getOpenIdToken = jest.fn().mockResolvedValue('this is your openid token');
 
-        sac.exchangeForScalarToken = sinon.stub().withArgs('this is your openid token').resolves('wokentoken');
+        sac.exchangeForScalarToken = jest.fn((arg) => {
+            if (arg === "this is your openid token") return Promise.resolve("wokentoken");
+        });
 
         await sac.connect();
 
-        expect(sac.exchangeForScalarToken.calledWith('this is your openid token')).toBeTruthy();
+        expect(sac.exchangeForScalarToken).toBeCalledWith('this is your openid token');
         expect(sac.scalarToken).toEqual('wokentoken');
     });
 });
diff --git a/test/Terms-test.js b/test/Terms-test.js
index 3fc7b56e42..71daafddfe 100644
--- a/test/Terms-test.js
+++ b/test/Terms-test.js
@@ -14,10 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-
-import sinon from 'sinon';
-
 import * as Matrix from 'matrix-js-sdk';
 
 import { startTermsFlow, Service } from '../src/Terms';
@@ -44,107 +40,100 @@ const IM_SERVICE_ONE = new Service(Matrix.SERVICE_TYPES.IM, 'https://imone.test'
 const IM_SERVICE_TWO = new Service(Matrix.SERVICE_TYPES.IM, 'https://imtwo.test', 'a token token');
 
 describe('Terms', function() {
-    let sandbox;
-
     beforeEach(function() {
-        sandbox = stubClient();
-    });
-
-    afterEach(function() {
-        sandbox.restore();
+        stubClient();
     });
 
     it('should prompt for all terms & services if no account data', async function() {
-        MatrixClientPeg.get().getAccountData = sinon.stub().returns(null);
-        MatrixClientPeg.get().getTerms = sinon.stub().returns({
+        MatrixClientPeg.get().getAccountData = jest.fn().mockReturnValue(null);
+        MatrixClientPeg.get().getTerms = jest.fn().mockReturnValue({
             policies: {
                 "policy_the_first": POLICY_ONE,
             },
         });
-        const interactionCallback = sinon.stub().resolves([]);
+        const interactionCallback = jest.fn().mockResolvedValue([]);
         await startTermsFlow([IM_SERVICE_ONE], interactionCallback);
-        console.log("interaction callback calls", interactionCallback.getCall(0));
+        console.log("interaction callback calls", interactionCallback.mock.calls[0]);
 
-        expect(interactionCallback.calledWith([
+        expect(interactionCallback).toBeCalledWith([
             {
                 service: IM_SERVICE_ONE,
                 policies: {
                     policy_the_first: POLICY_ONE,
                 },
             },
-        ])).toBeTruthy();
+        ], []);
     });
 
     it('should not prompt if all policies are signed in account data', async function() {
-        MatrixClientPeg.get().getAccountData = sinon.stub().returns({
-            getContent: sinon.stub().returns({
+        MatrixClientPeg.get().getAccountData = jest.fn().mockReturnValue({
+            getContent: jest.fn().mockReturnValue({
                 accepted: ["http://example.com/one"],
             }),
         });
-        MatrixClientPeg.get().getTerms = sinon.stub().returns({
+        MatrixClientPeg.get().getTerms = jest.fn().mockReturnValue({
             policies: {
                 "policy_the_first": POLICY_ONE,
             },
         });
-        MatrixClientPeg.get().agreeToTerms = sinon.stub();
+        MatrixClientPeg.get().agreeToTerms = jest.fn();
 
-        const interactionCallback = sinon.spy();
+        const interactionCallback = jest.fn();
         await startTermsFlow([IM_SERVICE_ONE], interactionCallback);
-        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.getCall(0).args);
+        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.mock.calls[0]);
 
-        expect(interactionCallback.called).toBeFalsy();
-        expect(MatrixClientPeg.get().agreeToTerms.calledWith(
+        expect(interactionCallback).not.toHaveBeenCalled();
+        expect(MatrixClientPeg.get().agreeToTerms).toBeCalledWith(
             Matrix.SERVICE_TYPES.IM,
             'https://imone.test',
             'a token token',
             ["http://example.com/one"],
-        )).toBeTruthy();
+        );
     });
 
     it("should prompt for only terms that aren't already signed", async function() {
-        MatrixClientPeg.get().getAccountData = sinon.stub().returns({
-            getContent: sinon.stub().returns({
+        MatrixClientPeg.get().getAccountData = jest.fn().mockReturnValue({
+            getContent: jest.fn().mockReturnValue({
                 accepted: ["http://example.com/one"],
             }),
         });
-        MatrixClientPeg.get().getTerms = sinon.stub().returns({
+        MatrixClientPeg.get().getTerms = jest.fn().mockReturnValue({
             policies: {
                 "policy_the_first": POLICY_ONE,
                 "policy_the_second": POLICY_TWO,
             },
         });
-        MatrixClientPeg.get().agreeToTerms = sinon.stub();
+        MatrixClientPeg.get().agreeToTerms = jest.fn();
 
-        const interactionCallback = sinon.stub().resolves(["http://example.com/one", "http://example.com/two"]);
+        const interactionCallback = jest.fn().mockResolvedValue(["http://example.com/one", "http://example.com/two"]);
         await startTermsFlow([IM_SERVICE_ONE], interactionCallback);
-        console.log("interactionCallback call", interactionCallback.getCall(0).args);
-        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.getCall(0).args);
+        console.log("interactionCallback call", interactionCallback.mock.calls[0]);
+        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.mock.calls[0]);
 
-        expect(interactionCallback.calledWith([
+        expect(interactionCallback).toBeCalledWith([
             {
                 service: IM_SERVICE_ONE,
                 policies: {
                     policy_the_second: POLICY_TWO,
                 },
             },
-        ])).toBeTruthy();
-        expect(MatrixClientPeg.get().agreeToTerms.calledWith(
+        ], ["http://example.com/one"]);
+        expect(MatrixClientPeg.get().agreeToTerms).toBeCalledWith(
             Matrix.SERVICE_TYPES.IM,
             'https://imone.test',
             'a token token',
             ["http://example.com/one", "http://example.com/two"],
-        )).toBeTruthy();
+        );
     });
 
     it("should prompt for only services with un-agreed policies", async function() {
-        MatrixClientPeg.get().getAccountData = sinon.stub().returns({
-            getContent: sinon.stub().returns({
+        MatrixClientPeg.get().getAccountData = jest.fn().mockReturnValue({
+            getContent: jest.fn().mockReturnValue({
                 accepted: ["http://example.com/one"],
             }),
         });
 
-        MatrixClientPeg.get().getTerms = sinon.stub();
-        MatrixClientPeg.get().getTerms.callsFake((serviceType, baseUrl, accessToken) => {
+        MatrixClientPeg.get().getTerms = jest.fn((serviceType, baseUrl, accessToken) => {
             switch (baseUrl) {
                 case 'https://imone.test':
                     return {
@@ -161,35 +150,35 @@ describe('Terms', function() {
             }
         });
 
-        MatrixClientPeg.get().agreeToTerms = sinon.stub();
+        MatrixClientPeg.get().agreeToTerms = jest.fn();
 
-        const interactionCallback = sinon.stub().resolves(["http://example.com/one", "http://example.com/two"]);
+        const interactionCallback = jest.fn().mockResolvedValue(["http://example.com/one", "http://example.com/two"]);
         await startTermsFlow([IM_SERVICE_ONE, IM_SERVICE_TWO], interactionCallback);
-        console.log("getTerms call 0", MatrixClientPeg.get().getTerms.getCall(0).args);
-        console.log("getTerms call 1", MatrixClientPeg.get().getTerms.getCall(1).args);
-        console.log("interactionCallback call", interactionCallback.getCall(0).args);
-        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.getCall(0).args);
+        // console.log("getTerms call 0", MatrixClientPeg.get().getTerms.getCall(0).args);
+        // console.log("getTerms call 1", MatrixClientPeg.get().getTerms.getCall(1).args);
+        // console.log("interactionCallback call", interactionCallback.getCall(0).args);
+        // console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.getCall(0).args);
 
-        expect(interactionCallback.calledWith([
+        expect(interactionCallback).toBeCalledWith([
             {
                 service: IM_SERVICE_TWO,
                 policies: {
                     policy_the_second: POLICY_TWO,
                 },
             },
-        ])).toBeTruthy();
-        expect(MatrixClientPeg.get().agreeToTerms.calledWith(
+        ], ["http://example.com/one"]);
+        expect(MatrixClientPeg.get().agreeToTerms).toBeCalledWith(
             Matrix.SERVICE_TYPES.IM,
             'https://imone.test',
             'a token token',
             ["http://example.com/one"],
-        )).toBeTruthy();
-        expect(MatrixClientPeg.get().agreeToTerms.calledWith(
+        );
+        expect(MatrixClientPeg.get().agreeToTerms).toBeCalledWith(
             Matrix.SERVICE_TYPES.IM,
             'https://imtwo.test',
             'a token token',
             ["http://example.com/two"],
-        )).toBeTruthy();
+        );
     });
 });
 
diff --git a/test/UserActivity-test.js b/test/UserActivity-test.js
index 6c684d25e9..a30df527ae 100644
--- a/test/UserActivity-test.js
+++ b/test/UserActivity-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import lolex from 'lolex';
 import jest from 'jest-mock';
 import EventEmitter from 'events';
diff --git a/test/all-tests.js b/test/all-tests.js
deleted file mode 100644
index 1d4d36ebfd..0000000000
--- a/test/all-tests.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// all-tests.js
-//
-// Our master test file: uses the webpack require API to find our test files
-// and run them
-
-const context = require.context('.', true, /-test\.jsx?$/);
-context.keys().forEach(context);
diff --git a/test/autocomplete/QueryMatcher-test.js b/test/autocomplete/QueryMatcher-test.js
index 864e1da81d..03f28eb984 100644
--- a/test/autocomplete/QueryMatcher-test.js
+++ b/test/autocomplete/QueryMatcher-test.js
@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-
 import QueryMatcher from '../../src/autocomplete/QueryMatcher';
 
 const OBJECTS = [
diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index 1319e312fb..57531a427c 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -17,14 +17,13 @@ limitations under the License.
 import React from 'react';
 import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
-import expect from 'expect';
 
 import MockHttpBackend from 'matrix-mock-request';
 import MatrixClientPeg from '../../../src/MatrixClientPeg';
-import sdk from 'matrix-react-sdk';
+import sdk from '../../skinned-sdk';
 import Matrix from 'matrix-js-sdk';
 
-import * as TestUtils from 'test-utils';
+import * as TestUtils from '../../test-utils';
 const { waitForUpdate } = TestUtils;
 
 const GroupView = sdk.getComponent('structures.GroupView');
diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js
index cd0a0bfcd7..88abaf6735 100644
--- a/test/components/structures/MessagePanel-test.js
+++ b/test/components/structures/MessagePanel-test.js
@@ -23,10 +23,9 @@ import ReactDOM from "react-dom";
 import PropTypes from "prop-types";
 const TestUtils = require('react-dom/test-utils');
 const expect = require('expect');
-import sinon from 'sinon';
 import { EventEmitter } from "events";
 
-const sdk = require('matrix-react-sdk');
+import sdk from '../../skinned-sdk';
 
 const MessagePanel = sdk.getComponent('structures.MessagePanel');
 import MatrixClientPeg from '../../../src/MatrixClientPeg';
@@ -72,15 +71,14 @@ describe('MessagePanel', function() {
     const clock = mockclock.clock();
     const realSetTimeout = window.setTimeout;
     const events = mkEvents();
-    let sandbox = null;
 
     beforeEach(function() {
-        sandbox = test_utils.stubClient();
+        test_utils.stubClient();
         client = MatrixClientPeg.get();
         client.credentials = {userId: '@me:here'};
 
         // HACK: We assume all settings want to be disabled
-        SettingsStore.getValue = sinon.stub().returns(false);
+        SettingsStore.getValue = jest.fn().returns(false);
         SettingsStore.getValue.withArgs('showDisplaynameChanges').returns(true);
 
         // This option clobbers the duration of all animations to be 1ms
@@ -94,7 +92,6 @@ describe('MessagePanel', function() {
         delete Velocity.mock;
 
         clock.uninstall();
-        sandbox.restore();
     });
 
     function mkEvents() {
diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js
index d06e754e3e..3520672cbe 100644
--- a/test/components/structures/auth/Login-test.js
+++ b/test/components/structures/auth/Login-test.js
@@ -14,12 +14,10 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-import sinon from 'sinon';
 import React from 'react';
 import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
-import sdk from 'matrix-react-sdk';
+import sdk from '../../../skinned-sdk';
 import SdkConfig from '../../../../src/SdkConfig';
 import {mkServerConfig} from "../../../test-utils";
 
@@ -36,7 +34,6 @@ describe('Login', function() {
     });
 
     afterEach(function() {
-        sinon.restore();
         ReactDOM.unmountComponentAtNode(parentDiv);
         parentDiv.remove();
     });
@@ -72,7 +69,7 @@ describe('Login', function() {
     });
 
     it('should show form without change server link when custom URLs disabled', function() {
-        sinon.stub(SdkConfig, "get").returns({
+        jest.spyOn(SdkConfig, "get").returns({
             disable_custom_urls: true,
         });
 
diff --git a/test/components/structures/auth/Registration-test.js b/test/components/structures/auth/Registration-test.js
index ad82597f8b..12f736640e 100644
--- a/test/components/structures/auth/Registration-test.js
+++ b/test/components/structures/auth/Registration-test.js
@@ -14,12 +14,10 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
-import sinon from 'sinon';
 import React from 'react';
 import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
-import sdk from 'matrix-react-sdk';
+import sdk from '../../../skinned-sdk';
 import SdkConfig from '../../../../src/SdkConfig';
 import {mkServerConfig} from "../../../test-utils";
 
@@ -36,7 +34,6 @@ describe('Registration', function() {
     });
 
     afterEach(function() {
-        sinon.restore();
         ReactDOM.unmountComponentAtNode(parentDiv);
         parentDiv.remove();
     });
@@ -61,7 +58,7 @@ describe('Registration', function() {
     });
 
     it('should show form when custom URLs disabled', function() {
-        sinon.stub(SdkConfig, "get").returns({
+        jest.spyOn(SdkConfig, "get").returns({
             disable_custom_urls: true,
         });
 
diff --git a/test/components/views/dialogs/InteractiveAuthDialog-test.js b/test/components/views/dialogs/InteractiveAuthDialog-test.js
index 5ceba1037b..fe7f538d7d 100644
--- a/test/components/views/dialogs/InteractiveAuthDialog-test.js
+++ b/test/components/views/dialogs/InteractiveAuthDialog-test.js
@@ -14,14 +14,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import React from 'react';
 import ReactDOM from 'react-dom';
 import ReactTestUtils from 'react-dom/test-utils';
-import sinon from 'sinon';
 import MatrixReactTestUtils from 'matrix-react-test-utils';
 
-import sdk from 'matrix-react-sdk';
+import sdk from '../../../skinned-sdk';
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
 
 import * as test_utils from '../../../test-utils';
@@ -33,10 +31,9 @@ const InteractiveAuthDialog = sdk.getComponent(
 
 describe('InteractiveAuthDialog', function() {
     let parentDiv;
-    let sandbox;
 
     beforeEach(function() {
-        sandbox = test_utils.stubClient(sandbox);
+        test_utils.stubClient();
         parentDiv = document.createElement('div');
         document.body.appendChild(parentDiv);
     });
@@ -44,12 +41,11 @@ describe('InteractiveAuthDialog', function() {
     afterEach(function() {
         ReactDOM.unmountComponentAtNode(parentDiv);
         parentDiv.remove();
-        sandbox.restore();
     });
 
     it('Should successfully complete a password flow', function() {
-        const onFinished = sinon.spy();
-        const doRequest = sinon.stub().returns(Promise.resolve({a: 1}));
+        const onFinished = jest.fn();
+        const doRequest = jest.fn().mockResolvedValue({a: 1});
 
         // tell the stub matrixclient to return a real userid
         const client = MatrixClientPeg.get();
@@ -108,8 +104,8 @@ describe('InteractiveAuthDialog', function() {
             // let the request complete
             return sleep(1);
         }).then(() => {
-            expect(onFinished.callCount).toEqual(1);
-            expect(onFinished.calledWithExactly(true, {a: 1})).toBe(true);
+            expect(onFinished).toBeCalledTimes(1);
+            expect(onFinished).toBeCalledWith(true, {a: 1});
         });
     });
 });
diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js
index ab69ae10be..e068a8e749 100644
--- a/test/components/views/elements/MemberEventListSummary-test.js
+++ b/test/components/views/elements/MemberEventListSummary-test.js
@@ -1,8 +1,7 @@
-import expect from 'expect';
 import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ShallowRenderer from "react-test-renderer/shallow";
-import sdk from 'matrix-react-sdk';
+import sdk from '../../../skinned-sdk';
 import * as languageHandler from '../../../../src/languageHandler';
 import * as testUtils from '../../../test-utils';
 
@@ -12,8 +11,6 @@ const MemberEventListSummary = testUtils.wrapInMatrixClientContext(
 );
 
 describe('MemberEventListSummary', function() {
-    let sandbox;
-
     // Generate dummy event tiles for use in simulating an expanded MELS
     const generateTiles = (events) => {
         return events.map((e) => {
@@ -88,7 +85,7 @@ describe('MemberEventListSummary', function() {
     };
 
     beforeEach(function(done) {
-        sandbox = testUtils.stubClient();
+        testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
         languageHandler.setMissingEntryGenerator(function(key) {
@@ -96,10 +93,6 @@ describe('MemberEventListSummary', function() {
         });
     });
 
-    afterEach(function() {
-        sandbox.restore();
-    });
-
     it('renders expanded events if there are less than props.threshold', function() {
         const events = generateEvents([
             {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index 6ebdbbd320..08f0f781ac 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -17,14 +17,13 @@ limitations under the License.
 import React from "react";
 import ReactDOM from "react-dom";
 import ReactTestUtils from "react-dom/test-utils";
-import expect from "expect";
 
 import MockHttpBackend from "matrix-mock-request";
 import MatrixClientPeg from "../../../../src/MatrixClientPeg";
-import sdk from "matrix-react-sdk";
+import sdk from "../../../skinned-sdk";
 import Matrix from "matrix-js-sdk";
 
-import * as TestUtils from "test-utils";
+import * as TestUtils from "../../../test-utils";
 const { waitForUpdate } = TestUtils;
 
 const GroupMemberList = sdk.getComponent("views.groups.GroupMemberList");
diff --git a/test/components/views/rooms/MemberList-test.js b/test/components/views/rooms/MemberList-test.js
index 2a275e1895..bc12041398 100644
--- a/test/components/views/rooms/MemberList-test.js
+++ b/test/components/views/rooms/MemberList-test.js
@@ -1,10 +1,9 @@
 import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ReactDOM from 'react-dom';
-import expect from 'expect';
 import lolex from 'lolex';
 
-import * as TestUtils from 'test-utils';
+import * as TestUtils from '../../../test-utils';
 
 import sdk from '../../../../src/index';
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
@@ -26,7 +25,6 @@ describe('MemberList', () => {
     }
 
     let parentDiv = null;
-    let sandbox = null;
     let client = null;
     let root = null;
     let clock = null;
@@ -38,7 +36,7 @@ describe('MemberList', () => {
     let defaultUsers = [];
 
     beforeEach(function() {
-        sandbox = TestUtils.stubClient(sandbox);
+        TestUtils.stubClient();
         client = MatrixClientPeg.get();
         client.hasLazyLoadMembersEnabled = () => false;
 
@@ -115,7 +113,6 @@ describe('MemberList', () => {
             parentDiv.remove();
             parentDiv = null;
         }
-        sandbox.restore();
 
         clock.uninstall();
 
diff --git a/test/components/views/rooms/MessageComposerInput-test.js b/test/components/views/rooms/MessageComposerInput-test.js
index 687bbac926..defdb8c69c 100644
--- a/test/components/views/rooms/MessageComposerInput-test.js
+++ b/test/components/views/rooms/MessageComposerInput-test.js
@@ -1,10 +1,8 @@
 import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ReactDOM from 'react-dom';
-import expect from 'expect';
-import sinon from 'sinon';
 import * as testUtils from '../../../test-utils';
-import sdk from 'matrix-react-sdk';
+import sdk from '../../../skinned-sdk';
 const MessageComposerInput = sdk.getComponent('views.rooms.MessageComposerInput');
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
 import {sleep} from "../../../../src/utils/promise";
@@ -23,13 +21,12 @@ function addTextToDraft(text) {
 
 xdescribe('MessageComposerInput', () => {
     let parentDiv = null,
-        sandbox = null,
         client = null,
         mci = null,
         room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
 
     beforeEach(function() {
-        sandbox = testUtils.stubClient(sandbox);
+        testUtils.stubClient();
         client = MatrixClientPeg.get();
         client.credentials = {userId: '@me:domain.com'};
 
@@ -54,7 +51,6 @@ xdescribe('MessageComposerInput', () => {
                 parentDiv.remove();
                 parentDiv = null;
             }
-            sandbox.restore();
             done();
         });
     });
@@ -75,66 +71,66 @@ xdescribe('MessageComposerInput', () => {
     });
 
     it('should not send messages when composer is empty', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(true);
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
-        expect(spy.calledOnce).toEqual(false, 'should not send message');
+        expect(spy).not.toBeCalled();
     });
 
     it('should not change content unnecessarily on RTE -> Markdown conversion', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(true);
         addTextToDraft('a');
         mci.handleKeyCommand('toggle-mode');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('a');
     });
 
     it('should not change content unnecessarily on Markdown -> RTE conversion', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('a');
         mci.handleKeyCommand('toggle-mode');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('a');
     });
 
     it('should send emoji messages when rich text is enabled', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(true);
         addTextToDraft('☹');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true, 'should send message');
     });
 
     it('should send emoji messages when Markdown is enabled', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('☹');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true, 'should send message');
     });
 
     // FIXME
     // it('should convert basic Markdown to rich text correctly', () => {
-    //     const spy = sinon.spy(client, 'sendHtmlMessage');
+    //     const spy = jest.spyOn(client, 'sendHtmlMessage');
     //     mci.enableRichtext(false);
     //     addTextToDraft('*abc*');
     //     mci.handleKeyCommand('toggle-mode');
-    //     mci.handleReturn(sinon.stub());
+    //     mci.handleReturn(jest.fn());
     //     console.error(spy.args[0][2]);
     //     expect(spy.args[0][2]).toContain('<em>abc');
     // });
     //
     // it('should convert basic rich text to Markdown correctly', () => {
-    //     const spy = sinon.spy(client, 'sendHtmlMessage');
+    //     const spy = jest.spyOn(client, 'sendHtmlMessage');
     //     mci.enableRichtext(true);
     //     process.nextTick(() => {
     //
@@ -142,43 +138,43 @@ xdescribe('MessageComposerInput', () => {
     //     mci.handleKeyCommand('italic');
     //     addTextToDraft('abc');
     //     mci.handleKeyCommand('toggle-mode');
-    //     mci.handleReturn(sinon.stub());
+    //     mci.handleReturn(jest.fn());
     //     expect(['_abc_', '*abc*']).toContain(spy.args[0][1]);
     // });
 
     it('should insert formatting characters in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         mci.handleKeyCommand('italic');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
         expect(['__', '**']).toContain(spy.args[0][1].body);
     });
 
     it('should not entity-encode " in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('"');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('"');
     });
 
     it('should escape characters without other markup in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('\\*escaped\\*');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('*escaped*');
     });
 
     it('should escape characters with other markup in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('\\*escaped\\* *italic*');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('\\*escaped\\* *italic*');
@@ -186,20 +182,20 @@ xdescribe('MessageComposerInput', () => {
     });
 
     it('should not convert -_- into a horizontal rule in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('-_-');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('-_-');
     });
 
     it('should not strip <del> tags in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('<del>striked-out</del>');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('<del>striked-out</del>');
@@ -207,30 +203,30 @@ xdescribe('MessageComposerInput', () => {
     });
 
     it('should not strike-through ~~~ in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('~~~striked-out~~~');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('~~~striked-out~~~');
     });
 
     it('should not mark single unmarkedup paragraphs as HTML in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
     });
 
     it('should not mark two unmarkedup paragraphs as HTML in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         addTextToDraft('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nFusce congue sapien sed neque molestie volutpat.');
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.calledOnce).toEqual(true);
         expect(spy.args[0][1].body).toEqual('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nFusce congue sapien sed neque molestie volutpat.');
@@ -238,7 +234,7 @@ xdescribe('MessageComposerInput', () => {
 
     it('should strip tab-completed mentions so that only the display name is sent in the plain body in Markdown mode', () => {
         // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(false);
         mci.setDisplayedCompletion({
             completion: 'Some Member',
@@ -246,7 +242,7 @@ xdescribe('MessageComposerInput', () => {
             href: `https://matrix.to/#/@some_member:domain.bla`,
         });
 
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.args[0][1].body).toEqual(
             'Some Member',
@@ -260,7 +256,7 @@ xdescribe('MessageComposerInput', () => {
 
     it('should strip tab-completed mentions so that only the display name is sent in the plain body in RTE mode', () => {
         // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         mci.enableRichtext(true);
         mci.setDisplayedCompletion({
             completion: 'Some Member',
@@ -268,7 +264,7 @@ xdescribe('MessageComposerInput', () => {
             href: `https://matrix.to/#/@some_member:domain.bla`,
         });
 
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.args[0][1].body).toEqual('Some Member');
         expect(spy.args[0][1].formatted_body).toEqual('<a href="https://matrix.to/#/@some_member:domain.bla">Some Member</a>');
@@ -276,12 +272,12 @@ xdescribe('MessageComposerInput', () => {
 
     it('should not strip non-tab-completed mentions when manually typing MD', () => {
         // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         // Markdown mode enabled
         mci.enableRichtext(false);
         addTextToDraft('[My Not-Tab-Completed Mention](https://matrix.to/#/@some_member:domain.bla)');
 
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.args[0][1].body).toEqual('[My Not-Tab-Completed Mention](https://matrix.to/#/@some_member:domain.bla)');
         expect(spy.args[0][1].formatted_body).toEqual('<a href="https://matrix.to/#/@some_member:domain.bla">My Not-Tab-Completed Mention</a>');
@@ -289,12 +285,12 @@ xdescribe('MessageComposerInput', () => {
 
     it('should not strip arbitrary typed (i.e. not tab-completed) MD links', () => {
         // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
+        const spy = jest.spyOn(client, 'sendMessage');
         // Markdown mode enabled
         mci.enableRichtext(false);
         addTextToDraft('[Click here](https://some.lovely.url)');
 
-        mci.handleReturn(sinon.stub());
+        mci.handleReturn(jest.fn());
 
         expect(spy.args[0][1].body).toEqual('[Click here](https://some.lovely.url)');
         expect(spy.args[0][1].formatted_body).toEqual('<a href="https://some.lovely.url">Click here</a>');
diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js
index cea2105480..446abede3d 100644
--- a/test/components/views/rooms/RoomList-test.js
+++ b/test/components/views/rooms/RoomList-test.js
@@ -1,10 +1,9 @@
 import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ReactDOM from 'react-dom';
-import expect from 'expect';
 import lolex from 'lolex';
 
-import * as TestUtils from 'test-utils';
+import * as TestUtils from '../../../test-utils';
 
 import sdk from '../../../../src/index';
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
@@ -31,7 +30,6 @@ describe('RoomList', () => {
     }
 
     let parentDiv = null;
-    let sandbox = null;
     let client = null;
     let root = null;
     const myUserId = '@me:domain';
@@ -45,7 +43,7 @@ describe('RoomList', () => {
     let myOtherMember;
 
     beforeEach(function() {
-        sandbox = TestUtils.stubClient(sandbox);
+        TestUtils.stubClient();
         client = MatrixClientPeg.get();
         client.credentials = {userId: myUserId};
         //revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value
@@ -111,7 +109,6 @@ describe('RoomList', () => {
             parentDiv.remove();
             parentDiv = null;
         }
-        sandbox.restore();
 
         clock.uninstall();
 
diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js
index 2608eb488a..7b7c554a2c 100644
--- a/test/components/views/rooms/RoomSettings-test.js
+++ b/test/components/views/rooms/RoomSettings-test.js
@@ -1,190 +1,187 @@
 // TODO: Rewrite room settings tests for dialog support
-// import React from 'react';
-// import ReactDOM from 'react-dom';
-// import expect from 'expect';
-// import jest from 'jest-mock';
-// import * as testUtils from '../../../test-utils';
-// import sdk from 'matrix-react-sdk';
-// const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
-// import MatrixClientPeg from '../../../../src/MatrixClientPeg';
-// import SettingsStore from '../../../../src/settings/SettingsStore';
-//
-//
-// describe('RoomSettings', () => {
-//     let parentDiv = null;
-//     let sandbox = null;
-//     let client = null;
-//     let roomSettings = null;
-//     const room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
-//
-//     function expectSentStateEvent(roomId, eventType, expectedEventContent) {
-//         let found = false;
-//         for (const call of client.sendStateEvent.mock.calls) {
-//             const [
-//                 actualRoomId,
-//                 actualEventType,
-//                 actualEventContent,
-//             ] = call.slice(0, 3);
-//
-//             if (roomId === actualRoomId && actualEventType === eventType) {
-//                 expect(actualEventContent).toEqual(expectedEventContent);
-//                 found = true;
-//                 break;
-//             }
-//         }
-//         expect(found).toBe(true);
-//     }
-//
-//     beforeEach(function(done) {
-//         sandbox = testUtils.stubClient();
-//         client = MatrixClientPeg.get();
-//         client.credentials = {userId: '@me:domain.com'};
-//
-//         client.setRoomName = jest.fn().mockReturnValue(Promise.resolve());
-//         client.setRoomTopic = jest.fn().mockReturnValue(Promise.resolve());
-//         client.setRoomDirectoryVisibility = jest.fn().mockReturnValue(Promise.resolve());
-//
-//         // Covers any room state event (e.g. name, avatar, topic)
-//         client.sendStateEvent = jest.fn().mockReturnValue(Promise.resolve());
-//
-//         // Covers room tagging
-//         client.setRoomTag = jest.fn().mockReturnValue(Promise.resolve());
-//         client.deleteRoomTag = jest.fn().mockReturnValue(Promise.resolve());
-//
-//         // Covers any setting in the SettingsStore
-//         // (including local client settings not stored via matrix)
-//         SettingsStore.setValue = jest.fn().mockReturnValue(Promise.resolve());
-//
-//         parentDiv = document.createElement('div');
-//         document.body.appendChild(parentDiv);
-//
-//         const gatherWrappedRef = (r) => {roomSettings = r;};
-//
-//         // get use wrappedRef because we're using wrapInMatrixClientContext
-//         ReactDOM.render(
-//             <WrappedRoomSettings
-//                 wrappedRef={gatherWrappedRef}
-//                 room={room}
-//             />,
-//             parentDiv,
-//             done,
-//         );
-//     });
-//
-//     afterEach((done) => {
-//         if (parentDiv) {
-//             ReactDOM.unmountComponentAtNode(parentDiv);
-//             parentDiv.remove();
-//             parentDiv = null;
-//         }
-//         sandbox.restore();
-//         done();
-//     });
-//
-//     it('should not set when no setting is changed', (done) => {
-//         roomSettings.save().then(() => {
-//             expect(client.sendStateEvent).not.toHaveBeenCalled();
-//             expect(client.setRoomTag).not.toHaveBeenCalled();
-//             expect(client.deleteRoomTag).not.toHaveBeenCalled();
-//             done();
-//         });
-//     });
-//
-//     // XXX: Apparently we do call SettingsStore.setValue
-//     xit('should not settings via the SettingsStore when no setting is changed', (done) => {
-//         roomSettings.save().then(() => {
-//             expect(SettingsStore.setValue).not.toHaveBeenCalled();
-//             done();
-//         });
-//     });
-//
-//     it('should set room name when it has changed', (done) => {
-//         const name = "My Room Name";
-//         roomSettings.setName(name);
-//
-//         roomSettings.save().then(() => {
-//             expect(client.setRoomName.mock.calls[0].slice(0, 2))
-//                 .toEqual(['!DdJkzRliezrwpNebLk:matrix.org', name]);
-//
-//             done();
-//         });
-//     });
-//
-//     it('should set room topic when it has changed', (done) => {
-//         const topic = "this is a topic";
-//         roomSettings.setTopic(topic);
-//
-//         roomSettings.save().then(() => {
-//             expect(client.setRoomTopic.mock.calls[0].slice(0, 2))
-//                 .toEqual(['!DdJkzRliezrwpNebLk:matrix.org', topic]);
-//
-//             done();
-//         });
-//     });
-//
-//     it('should set history visibility when it has changed', (done) => {
-//         const historyVisibility = "translucent";
-//         roomSettings.setState({
-//             history_visibility: historyVisibility,
-//         });
-//
-//         roomSettings.save().then(() => {
-//             expectSentStateEvent(
-//                 "!DdJkzRliezrwpNebLk:matrix.org",
-//                 "m.room.history_visibility", {history_visibility: historyVisibility},
-//             );
-//             done();
-//         });
-//     });
-//
-//     // XXX: Can't test this because we `getRoomDirectoryVisibility` in `componentWillMount`
-//     xit('should set room directory publicity when set to true', (done) => {
-//         const isRoomPublished = true;
-//         roomSettings.setState({
-//             isRoomPublished,
-//         }, () => {
-//             roomSettings.save().then(() => {
-//                 expect(client.setRoomDirectoryVisibility.calls[0].arguments.slice(0, 2))
-//                     .toEqual("!DdJkzRliezrwpNebLk:matrix.org", isRoomPublished ? "public" : "private");
-//                 done();
-//             });
-//         });
-//     });
-//
-//     it('should set power levels when changed', (done) => {
-//         roomSettings.onPowerLevelsChanged(42, "invite");
-//
-//         roomSettings.save().then(() => {
-//             expectSentStateEvent(
-//                 "!DdJkzRliezrwpNebLk:matrix.org",
-//                 "m.room.power_levels", { invite: 42 },
-//             );
-//             done();
-//         });
-//     });
-//
-//     it('should set event power levels when changed', (done) => {
-//         roomSettings.onPowerLevelsChanged(42, "event_levels_m.room.message");
-//
-//         roomSettings.save().then(() => {
-//             // We expect all state events to be set to the state_default (50)
-//             // See powerLevelDescriptors in RoomSettings
-//             expectSentStateEvent(
-//                 "!DdJkzRliezrwpNebLk:matrix.org",
-//                 "m.room.power_levels", {
-//                     events: {
-//                         'm.room.message': 42,
-//                         'm.room.avatar': 50,
-//                         'm.room.name': 50,
-//                         'm.room.canonical_alias': 50,
-//                         'm.room.history_visibility': 50,
-//                         'm.room.power_levels': 50,
-//                         'm.room.topic': 50,
-//                         'im.vector.modular.widgets': 50,
-//                     },
-//                 },
-//             );
-//             done();
-//         });
-//     });
-// });
+import React from 'react';
+import ReactDOM from 'react-dom';
+import jest from 'jest-mock';
+import * as testUtils from '../../../test-utils';
+import sdk from '../../../skinned-sdk';
+const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
+import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import SettingsStore from '../../../../src/settings/SettingsStore';
+
+
+describe.skip('RoomSettings', () => {
+    let parentDiv = null;
+    let client = null;
+    let roomSettings = null;
+    const room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
+
+    function expectSentStateEvent(roomId, eventType, expectedEventContent) {
+        let found = false;
+        for (const call of client.sendStateEvent.mock.calls) {
+            const [
+                actualRoomId,
+                actualEventType,
+                actualEventContent,
+            ] = call.slice(0, 3);
+
+            if (roomId === actualRoomId && actualEventType === eventType) {
+                expect(actualEventContent).toEqual(expectedEventContent);
+                found = true;
+                break;
+            }
+        }
+        expect(found).toBe(true);
+    }
+
+    beforeEach(function(done) {
+        testUtils.stubClient();
+        client = MatrixClientPeg.get();
+        client.credentials = {userId: '@me:domain.com'};
+
+        client.setRoomName = jest.fn().mockReturnValue(Promise.resolve());
+        client.setRoomTopic = jest.fn().mockReturnValue(Promise.resolve());
+        client.setRoomDirectoryVisibility = jest.fn().mockReturnValue(Promise.resolve());
+
+        // Covers any room state event (e.g. name, avatar, topic)
+        client.sendStateEvent = jest.fn().mockReturnValue(Promise.resolve());
+
+        // Covers room tagging
+        client.setRoomTag = jest.fn().mockReturnValue(Promise.resolve());
+        client.deleteRoomTag = jest.fn().mockReturnValue(Promise.resolve());
+
+        // Covers any setting in the SettingsStore
+        // (including local client settings not stored via matrix)
+        SettingsStore.setValue = jest.fn().mockReturnValue(Promise.resolve());
+
+        parentDiv = document.createElement('div');
+        document.body.appendChild(parentDiv);
+
+        const gatherWrappedRef = (r) => {roomSettings = r;};
+
+        // get use wrappedRef because we're using wrapInMatrixClientContext
+        ReactDOM.render(
+            <WrappedRoomSettings
+                wrappedRef={gatherWrappedRef}
+                room={room}
+            />,
+            parentDiv,
+            done,
+        );
+    });
+
+    afterEach((done) => {
+        if (parentDiv) {
+            ReactDOM.unmountComponentAtNode(parentDiv);
+            parentDiv.remove();
+            parentDiv = null;
+        }
+        done();
+    });
+
+    it('should not set when no setting is changed', (done) => {
+        roomSettings.save().then(() => {
+            expect(client.sendStateEvent).not.toHaveBeenCalled();
+            expect(client.setRoomTag).not.toHaveBeenCalled();
+            expect(client.deleteRoomTag).not.toHaveBeenCalled();
+            done();
+        });
+    });
+
+    // XXX: Apparently we do call SettingsStore.setValue
+    xit('should not settings via the SettingsStore when no setting is changed', (done) => {
+        roomSettings.save().then(() => {
+            expect(SettingsStore.setValue).not.toHaveBeenCalled();
+            done();
+        });
+    });
+
+    it('should set room name when it has changed', (done) => {
+        const name = "My Room Name";
+        roomSettings.setName(name);
+
+        roomSettings.save().then(() => {
+            expect(client.setRoomName.mock.calls[0].slice(0, 2))
+                .toEqual(['!DdJkzRliezrwpNebLk:matrix.org', name]);
+
+            done();
+        });
+    });
+
+    it('should set room topic when it has changed', (done) => {
+        const topic = "this is a topic";
+        roomSettings.setTopic(topic);
+
+        roomSettings.save().then(() => {
+            expect(client.setRoomTopic.mock.calls[0].slice(0, 2))
+                .toEqual(['!DdJkzRliezrwpNebLk:matrix.org', topic]);
+
+            done();
+        });
+    });
+
+    it('should set history visibility when it has changed', (done) => {
+        const historyVisibility = "translucent";
+        roomSettings.setState({
+            history_visibility: historyVisibility,
+        });
+
+        roomSettings.save().then(() => {
+            expectSentStateEvent(
+                "!DdJkzRliezrwpNebLk:matrix.org",
+                "m.room.history_visibility", {history_visibility: historyVisibility},
+            );
+            done();
+        });
+    });
+
+    // XXX: Can't test this because we `getRoomDirectoryVisibility` in `componentWillMount`
+    xit('should set room directory publicity when set to true', (done) => {
+        const isRoomPublished = true;
+        roomSettings.setState({
+            isRoomPublished,
+        }, () => {
+            roomSettings.save().then(() => {
+                expect(client.setRoomDirectoryVisibility.calls[0].arguments.slice(0, 2))
+                    .toEqual("!DdJkzRliezrwpNebLk:matrix.org", isRoomPublished ? "public" : "private");
+                done();
+            });
+        });
+    });
+
+    it('should set power levels when changed', (done) => {
+        roomSettings.onPowerLevelsChanged(42, "invite");
+
+        roomSettings.save().then(() => {
+            expectSentStateEvent(
+                "!DdJkzRliezrwpNebLk:matrix.org",
+                "m.room.power_levels", { invite: 42 },
+            );
+            done();
+        });
+    });
+
+    it('should set event power levels when changed', (done) => {
+        roomSettings.onPowerLevelsChanged(42, "event_levels_m.room.message");
+
+        roomSettings.save().then(() => {
+            // We expect all state events to be set to the state_default (50)
+            // See powerLevelDescriptors in RoomSettings
+            expectSentStateEvent(
+                "!DdJkzRliezrwpNebLk:matrix.org",
+                "m.room.power_levels", {
+                    events: {
+                        'm.room.message': 42,
+                        'm.room.avatar': 50,
+                        'm.room.name': 50,
+                        'm.room.canonical_alias': 50,
+                        'm.room.history_visibility': 50,
+                        'm.room.power_levels': 50,
+                        'm.room.topic': 50,
+                        'im.vector.modular.widgets': 50,
+                    },
+                },
+            );
+            done();
+        });
+    });
+});
diff --git a/test/editor/caret-test.js b/test/editor/caret-test.js
index 9da28bff95..f0c171c7c9 100644
--- a/test/editor/caret-test.js
+++ b/test/editor/caret-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import {getLineAndNodePosition} from "../../src/editor/caret";
 import EditorModel from "../../src/editor/model";
 import {createPartCreator} from "./mock";
diff --git a/test/editor/deserialize-test.js b/test/editor/deserialize-test.js
index ae25e45126..1c58a6c40b 100644
--- a/test/editor/deserialize-test.js
+++ b/test/editor/deserialize-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import {parseEvent} from "../../src/editor/deserialize";
 import {createPartCreator} from "./mock";
 
diff --git a/test/editor/diff-test.js b/test/editor/diff-test.js
index ebcb058baa..4637206b27 100644
--- a/test/editor/diff-test.js
+++ b/test/editor/diff-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import {diffDeletion, diffAtCaret} from "../../src/editor/diff";
 
 describe('editor/diff', function() {
diff --git a/test/editor/history-test.js b/test/editor/history-test.js
index 4f227f74dd..e54c1e7ea9 100644
--- a/test/editor/history-test.js
+++ b/test/editor/history-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import HistoryManager, {MAX_STEP_LENGTH} from "../../src/editor/history";
 
 describe('editor/history', function() {
diff --git a/test/editor/model-test.js b/test/editor/model-test.js
index c5f2a2ef12..826dde3d68 100644
--- a/test/editor/model-test.js
+++ b/test/editor/model-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import EditorModel from "../../src/editor/model";
 import {createPartCreator} from "./mock";
 
diff --git a/test/editor/position-test.js b/test/editor/position-test.js
index 7ac4284c60..90f40c21a7 100644
--- a/test/editor/position-test.js
+++ b/test/editor/position-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import EditorModel from "../../src/editor/model";
 import {createPartCreator} from "./mock";
 
diff --git a/test/editor/range-test.js b/test/editor/range-test.js
index 468cb60c76..53fb6cb765 100644
--- a/test/editor/range-test.js
+++ b/test/editor/range-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import EditorModel from "../../src/editor/model";
 import {createPartCreator} from "./mock";
 
diff --git a/test/editor/serialize-test.js b/test/editor/serialize-test.js
index 2e7712e6e6..7517e46437 100644
--- a/test/editor/serialize-test.js
+++ b/test/editor/serialize-test.js
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import EditorModel from "../../src/editor/model";
 import {htmlSerializeIfNeeded} from "../../src/editor/serialize";
 import {createPartCreator} from "./mock";
diff --git a/test/i18n-test/languageHandler-test.js b/test/i18n-test/languageHandler-test.js
index 244fe99000..36dc4bed87 100644
--- a/test/i18n-test/languageHandler-test.js
+++ b/test/i18n-test/languageHandler-test.js
@@ -5,18 +5,12 @@ import * as languageHandler from '../../src/languageHandler';
 const testUtils = require('../test-utils');
 
 describe('languageHandler', function() {
-    let sandbox;
-
     beforeEach(function(done) {
-        sandbox = testUtils.stubClient();
+        testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
     });
 
-    afterEach(function() {
-        sandbox.restore();
-    });
-
     it('translates a string to german', function() {
         languageHandler.setLanguage('de').then(function() {
             const translated = languageHandler._t('Rooms');
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index 3762125cd9..249af84885 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -1,8 +1,5 @@
-import expect from 'expect';
-
 import RoomViewStore from '../../src/stores/RoomViewStore';
 
-
 import peg from '../../src/MatrixClientPeg';
 
 import * as testUtils from '../test-utils';
@@ -10,20 +7,14 @@ import * as testUtils from '../test-utils';
 const dispatch = testUtils.getDispatchForStore(RoomViewStore);
 
 describe('RoomViewStore', function() {
-    let sandbox;
-
     beforeEach(function() {
-        sandbox = testUtils.stubClient();
+        testUtils.stubClient();
         peg.get().credentials = { userId: "@test:example.com" };
 
         // Reset the state of the store
         RoomViewStore.reset();
     });
 
-    afterEach(function() {
-        sandbox.restore();
-    });
-
     it('can be used to view a room by ID and join', function(done) {
         peg.get().joinRoom = (roomAddress) => {
             expect(roomAddress).toBe("!randomcharacters:aser.ver");
diff --git a/test/test-utils.js b/test/test-utils.js
index 9e8768ae71..407791e9c3 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -1,6 +1,5 @@
 "use strict";
 
-import sinon from 'sinon';
 import React from 'react';
 import PropTypes from 'prop-types';
 import peg from '../src/MatrixClientPeg';
@@ -27,8 +26,6 @@ export function getRenderer() {
  * @returns {sinon.Sandbox}; remember to call sandbox.restore afterwards.
  */
 export function stubClient() {
-    const sandbox = sinon.sandbox.create();
-
     const client = createTestClient();
 
     // stub out the methods in MatrixClientPeg
@@ -37,12 +34,11 @@ export function stubClient() {
     // so we do this for each method
     const methods = ['get', 'unset', 'replaceUsingCreds'];
     for (let i = 0; i < methods.length; i++) {
-        sandbox.stub(peg, methods[i]);
+        peg[methods[i]] = jest.spyOn(peg, methods[i]);
     }
     // MatrixClientPeg.get() is called a /lot/, so implement it with our own
     // fast stub function rather than a sinon stub
     peg.get = function() { return client; };
-    return sandbox;
 }
 
 /**
@@ -52,27 +48,27 @@ export function stubClient() {
  */
 export function createTestClient() {
     return {
-        getHomeserverUrl: sinon.stub(),
-        getIdentityServerUrl: sinon.stub(),
-        getDomain: sinon.stub().returns("matrix.rog"),
-        getUserId: sinon.stub().returns("@userId:matrix.rog"),
+        getHomeserverUrl: jest.fn(),
+        getIdentityServerUrl: jest.fn(),
+        getDomain: jest.fn().mockReturnValue("matrix.rog"),
+        getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"),
 
-        getPushActionsForEvent: sinon.stub(),
-        getRoom: sinon.stub().returns(mkStubRoom()),
-        getRooms: sinon.stub().returns([]),
-        getVisibleRooms: sinon.stub().returns([]),
-        getGroups: sinon.stub().returns([]),
-        loginFlows: sinon.stub(),
-        on: sinon.stub(),
-        removeListener: sinon.stub(),
-        isRoomEncrypted: sinon.stub().returns(false),
-        peekInRoom: sinon.stub().returns(Promise.resolve(mkStubRoom())),
+        getPushActionsForEvent: jest.fn(),
+        getRoom: jest.fn().mockReturnValue(mkStubRoom()),
+        getRooms: jest.fn().mockReturnValue([]),
+        getVisibleRooms: jest.fn().mockReturnValue([]),
+        getGroups: jest.fn().mockReturnValue([]),
+        loginFlows: jest.fn(),
+        on: jest.fn(),
+        removeListener: jest.fn(),
+        isRoomEncrypted: jest.fn().mockReturnValue(false),
+        peekInRoom: jest.fn().mockResolvedValue(mkStubRoom()),
 
-        paginateEventTimeline: sinon.stub().returns(Promise.resolve()),
-        sendReadReceipt: sinon.stub().returns(Promise.resolve()),
-        getRoomIdForAlias: sinon.stub().returns(Promise.resolve()),
-        getRoomDirectoryVisibility: sinon.stub().returns(Promise.resolve()),
-        getProfileInfo: sinon.stub().returns(Promise.resolve({})),
+        paginateEventTimeline: jest.fn().mockResolvedValue(undefined),
+        sendReadReceipt: jest.fn().mockResolvedValue(undefined),
+        getRoomIdForAlias: jest.fn().mockResolvedValue(undefined),
+        getRoomDirectoryVisibility: jest.fn().mockResolvedValue(undefined),
+        getProfileInfo: jest.fn().mockResolvedValue({}),
         getAccountData: (type) => {
             return mkEvent({
                 type,
@@ -81,9 +77,9 @@ export function createTestClient() {
             });
         },
         mxcUrlToHttp: (mxc) => 'http://this.is.a.url/',
-        setAccountData: sinon.stub(),
-        sendTyping: sinon.stub().returns(Promise.resolve({})),
-        sendMessage: () => Promise.resolve({}),
+        setAccountData: jest.fn(),
+        sendTyping: jest.fn().mockResolvedValue({}),
+        sendMessage: () => jest.fn().mockResolvedValue({}),
         getSyncState: () => "SYNCING",
         generateClientSecret: () => "t35tcl1Ent5ECr3T",
         isGuest: () => false,
@@ -214,15 +210,15 @@ export function mkStubRoom(roomId = null) {
     const stubTimeline = { getEvents: () => [] };
     return {
         roomId,
-        getReceiptsForEvent: sinon.stub().returns([]),
-        getMember: sinon.stub().returns({
+        getReceiptsForEvent: jest.fn().mockReturnValue([]),
+        getMember: jest.fn().mockReturnValue({
             userId: '@member:domain.bla',
             name: 'Member',
             roomId: roomId,
             getAvatarUrl: () => 'mxc://avatar.url/image.png',
         }),
-        getMembersWithMembership: sinon.stub().returns([]),
-        getJoinedMembers: sinon.stub().returns([]),
+        getMembersWithMembership: jest.fn().mockReturnValue([]),
+        getJoinedMembers: jest.fn().mockReturnValue([]),
         getPendingEvents: () => [],
         getLiveTimeline: () => stubTimeline,
         getUnfilteredTimelineSet: () => null,
@@ -231,12 +227,12 @@ export function mkStubRoom(roomId = null) {
         getVersion: () => '1',
         shouldUpgradeToVersion: () => null,
         getMyMembership: () => "join",
-        maySendMessage: sinon.stub().returns(true),
+        maySendMessage: jest.fn().mockReturnValue(true),
         currentState: {
-            getStateEvents: sinon.stub(),
-            mayClientSendStateEvent: sinon.stub().returns(true),
-            maySendStateEvent: sinon.stub().returns(true),
-            maySendEvent: sinon.stub().returns(true),
+            getStateEvents: jest.fn(),
+            mayClientSendStateEvent: jest.fn().mockReturnValue(true),
+            maySendStateEvent: jest.fn().mockReturnValue(true),
+            maySendEvent: jest.fn().mockReturnValue(true),
             members: [],
         },
         tags: {
@@ -244,9 +240,9 @@ export function mkStubRoom(roomId = null) {
                 order: 0.5,
             },
         },
-        setBlacklistUnverifiedDevices: sinon.stub(),
-        on: sinon.stub(),
-        removeListener: sinon.stub(),
+        setBlacklistUnverifiedDevices: jest.fn(),
+        on: jest.fn(),
+        removeListener: jest.fn(),
     };
 }
 
@@ -295,7 +291,7 @@ export function wrapInMatrixClientContext(WrappedComponent) {
 /**
  * Call fn before calling componentDidUpdate on a react component instance, inst.
  * @param {React.Component} inst an instance of a React component.
- * @param {integer} updates Number of updates to wait for. (Defaults to 1.)
+ * @param {number} updates Number of updates to wait for. (Defaults to 1.)
  * @returns {Promise} promise that resolves when componentDidUpdate is called on
  *                    given component instance.
  */
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index a1dae391e6..0973f75a31 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -16,9 +16,7 @@ limitations under the License.
 
 "use strict";
 
-import * as MegolmExportEncryption from '../../src/utils/MegolmExportEncryption';
-
-import expect from 'expect';
+import SubtleCrypto from 'subtle';
 
 const TEST_VECTORS=[
     [
@@ -58,19 +56,22 @@ const TEST_VECTORS=[
         "bWnSXS9oymiqwUIGs08sXI33ZA==\n" +
         "-----END MEGOLM SESSION DATA-----",
     ],
-]
-;
+];
 
 function stringToArray(s) {
     return new TextEncoder().encode(s).buffer;
 }
 
 describe('MegolmExportEncryption', function() {
-    before(function() {
-        // if we don't have subtlecrypto, go home now
-        if (!window.crypto.subtle && !window.crypto.webkitSubtle) {
-            this.skip();
-        }
+    let MegolmExportEncryption;
+
+    beforeAll(() => {
+        window.crypto = { subtle: SubtleCrypto };
+        MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
+    });
+
+    afterAll(() => {
+        window.crypto = undefined;
     });
 
     describe('decrypt', function() {
diff --git a/test/utils/permalinks/Permalinks-test.js b/test/utils/permalinks/Permalinks-test.js
index 2f58afc380..05be3a6e5b 100644
--- a/test/utils/permalinks/Permalinks-test.js
+++ b/test/utils/permalinks/Permalinks-test.js
@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import expect from 'expect';
 import peg from '../../../src/MatrixClientPeg';
 import {
     makeGroupPermalink,
@@ -66,17 +65,11 @@ function mockRoom(roomId, members, serverACL) {
 }
 
 describe('Permalinks', function() {
-    let sandbox;
-
     beforeEach(function() {
-        sandbox = testUtils.stubClient();
+        testUtils.stubClient();
         peg.get().credentials = { userId: "@test:example.com" };
     });
 
-    afterEach(function() {
-        sandbox.restore();
-    });
-
     it('should pick no candidate servers when the room has no members', function() {
         const room = mockRoom("!fake:example.org", []);
         const creator = new RoomPermalinkCreator(room);
diff --git a/yarn.lock b/yarn.lock
index a84fe7b76f..61a8c49591 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -125,42 +125,6 @@
     lodash "^4.17.13"
     to-fast-properties "^2.0.0"
 
-"@jest/console@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0"
-  integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==
-  dependencies:
-    "@jest/source-map" "^24.9.0"
-    chalk "^2.0.1"
-    slash "^2.0.0"
-
-"@jest/source-map@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714"
-  integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==
-  dependencies:
-    callsites "^3.0.0"
-    graceful-fs "^4.1.15"
-    source-map "^0.6.0"
-
-"@jest/test-result@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca"
-  integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==
-  dependencies:
-    "@jest/console" "^24.9.0"
-    "@jest/types" "^24.9.0"
-    "@types/istanbul-lib-coverage" "^2.0.0"
-
-"@jest/types@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59"
-  integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==
-  dependencies:
-    "@types/istanbul-lib-coverage" "^2.0.0"
-    "@types/istanbul-reports" "^1.1.1"
-    "@types/yargs" "^13.0.0"
-
 "@mrmlnc/readdir-enhanced@^2.2.1":
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -174,42 +138,6 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
-"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0":
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393"
-  integrity sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==
-  dependencies:
-    type-detect "4.0.8"
-
-"@sinonjs/formatio@^2.0.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2"
-  integrity sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==
-  dependencies:
-    samsam "1.3.0"
-
-"@sinonjs/formatio@^3.2.1":
-  version "3.2.2"
-  resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c"
-  integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==
-  dependencies:
-    "@sinonjs/commons" "^1"
-    "@sinonjs/samsam" "^3.1.0"
-
-"@sinonjs/samsam@^3.1.0":
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a"
-  integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==
-  dependencies:
-    "@sinonjs/commons" "^1.3.0"
-    array-from "^2.1.1"
-    lodash "^4.17.15"
-
-"@sinonjs/text-encoding@^0.7.1":
-  version "0.7.1"
-  resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
-  integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
-
 "@types/events@*":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -224,26 +152,6 @@
     "@types/minimatch" "*"
     "@types/node" "*"
 
-"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
-  integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
-
-"@types/istanbul-lib-report@*":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
-  integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
-  dependencies:
-    "@types/istanbul-lib-coverage" "*"
-
-"@types/istanbul-reports@^1.1.1":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
-  integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
-  dependencies:
-    "@types/istanbul-lib-coverage" "*"
-    "@types/istanbul-lib-report" "*"
-
 "@types/json-schema@^7.0.3":
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
@@ -259,11 +167,6 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2"
   integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==
 
-"@types/stack-utils@^1.0.1":
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
-  integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
-
 "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@@ -285,18 +188,6 @@
     "@types/unist" "*"
     "@types/vfile-message" "*"
 
-"@types/yargs-parser@*":
-  version "13.1.0"
-  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228"
-  integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==
-
-"@types/yargs@^13.0.0":
-  version "13.0.3"
-  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380"
-  integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==
-  dependencies:
-    "@types/yargs-parser" "*"
-
 "@typescript-eslint/experimental-utils@^2.5.0":
   version "2.10.0"
   resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz#8db1656cdfd3d9dcbdbf360b8274dea76f0b2c2c"
@@ -592,7 +483,7 @@ ansi-regex@^3.0.0:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
   integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
 
-ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+ansi-regex@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
   integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
@@ -692,11 +583,6 @@ array-find-index@^1.0.1:
   resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
   integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
 
-array-from@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195"
-  integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=
-
 array-includes@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
@@ -1649,6 +1535,11 @@ blob@0.0.5:
   resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
   integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
 
+bluebird@^2.9.27:
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
+  integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
+
 bluebird@^3.3.0, bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -2689,12 +2580,7 @@ diff-match-patch@^1.0.4:
   resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
   integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
 
-diff-sequences@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
-  integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
-
-diff@3.5.0, diff@^3.2.0, diff@^3.5.0:
+diff@3.5.0, diff@^3.2.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
@@ -2813,6 +2699,13 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
+ecc-jsbn@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.0.1.tgz#970577ba31b4976fb1889a298cb7451d896c466d"
+  integrity sha1-lwV3ujG0l2+xiJopjLdFHYlsRm0=
+  dependencies:
+    jsbn "git+https://github.com/rynomad/jsbn.git"
+
 ecc-jsbn@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@@ -2821,6 +2714,12 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
+"ecc-qj@git+https://github.com/rynomad/ecc.git":
+  version "0.0.1"
+  resolved "git+https://github.com/rynomad/ecc.git#a8c599363dab87a5c95274338d863233f00f7c4a"
+  dependencies:
+    nan "^1.6.2"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -3370,18 +3269,6 @@ expect@^23.6.0:
     jest-message-util "^23.4.0"
     jest-regex-util "^23.3.0"
 
-expect@^24.1.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca"
-  integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==
-  dependencies:
-    "@jest/types" "^24.9.0"
-    ansi-styles "^3.2.0"
-    jest-get-type "^24.9.0"
-    jest-matcher-utils "^24.9.0"
-    jest-message-util "^24.9.0"
-    jest-regex-util "^24.9.0"
-
 extend-shallow@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -4947,11 +4834,6 @@ is-wsl@^1.1.0:
   resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
   integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
 
-isarray@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
-  integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
 isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -5158,16 +5040,6 @@ jest-diff@^23.6.0:
     jest-get-type "^22.1.0"
     pretty-format "^23.6.0"
 
-jest-diff@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
-  integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
-  dependencies:
-    chalk "^2.0.1"
-    diff-sequences "^24.9.0"
-    jest-get-type "^24.9.0"
-    pretty-format "^24.9.0"
-
 jest-docblock@^23.2.0:
   version "23.2.0"
   resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
@@ -5205,11 +5077,6 @@ jest-get-type@^22.1.0:
   resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
   integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
 
-jest-get-type@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
-  integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
-
 jest-haste-map@^23.6.0:
   version "23.6.0"
   resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
@@ -5258,16 +5125,6 @@ jest-matcher-utils@^23.6.0:
     jest-get-type "^22.1.0"
     pretty-format "^23.6.0"
 
-jest-matcher-utils@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073"
-  integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==
-  dependencies:
-    chalk "^2.0.1"
-    jest-diff "^24.9.0"
-    jest-get-type "^24.9.0"
-    pretty-format "^24.9.0"
-
 jest-message-util@^23.4.0:
   version "23.4.0"
   resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
@@ -5279,20 +5136,6 @@ jest-message-util@^23.4.0:
     slash "^1.0.0"
     stack-utils "^1.0.1"
 
-jest-message-util@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3"
-  integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==
-  dependencies:
-    "@babel/code-frame" "^7.0.0"
-    "@jest/test-result" "^24.9.0"
-    "@jest/types" "^24.9.0"
-    "@types/stack-utils" "^1.0.1"
-    chalk "^2.0.1"
-    micromatch "^3.1.10"
-    slash "^2.0.0"
-    stack-utils "^1.0.1"
-
 jest-mock@^23.2.0:
   version "23.2.0"
   resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
@@ -5303,11 +5146,6 @@ jest-regex-util@^23.3.0:
   resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
   integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
 
-jest-regex-util@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636"
-  integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==
-
 jest-resolve-dependencies@^23.6.0:
   version "23.6.0"
   resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
@@ -5471,6 +5309,10 @@ js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.7.0:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
+"jsbn@git+https://github.com/rynomad/jsbn.git":
+  version "0.0.0"
+  resolved "git+https://github.com/rynomad/jsbn.git#bb522b0124f75424f89d49446c40a87111942c7b"
+
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -5592,11 +5434,6 @@ jsx-ast-utils@^2.2.3:
     array-includes "^3.0.3"
     object.assign "^4.1.0"
 
-just-extend@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc"
-  integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==
-
 karma-chrome-launcher@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
@@ -5830,11 +5667,6 @@ lodash.escaperegexp@^4.1.2:
   resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
   integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
 
-lodash.get@^4.4.2:
-  version "4.4.2"
-  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
-  integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
-
 lodash.isboolean@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
@@ -5898,16 +5730,11 @@ loglevel@^1.6.4:
   resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312"
   integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==
 
-lolex@4.2, lolex@^4.1.0:
+lolex@4.2:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7"
   integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==
 
-lolex@^2.4.2:
-  version "2.7.5"
-  resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733"
-  integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==
-
 longest-streak@^2.0.1:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.3.tgz#3de7a3f47ee18e9074ded8575b5c091f5d0a4105"
@@ -6368,6 +6195,11 @@ mute-stream@0.0.7:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
+nan@^1.6.2:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-1.9.0.tgz#1a9cd2755609766f5c291e4194fce39fde286515"
+  integrity sha1-GpzSdVYJdm9cKR5BlPzjn94oZRU=
+
 nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
@@ -6419,17 +6251,6 @@ nice-try@^1.0.4:
   resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
   integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
 
-nise@^1.3.3:
-  version "1.5.2"
-  resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.2.tgz#b6d29af10e48b321b307e10e065199338eeb2652"
-  integrity sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==
-  dependencies:
-    "@sinonjs/formatio" "^3.2.1"
-    "@sinonjs/text-encoding" "^0.7.1"
-    just-extend "^4.0.2"
-    lolex "^4.1.0"
-    path-to-regexp "^1.7.0"
-
 node-fetch-npm@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
@@ -6447,6 +6268,11 @@ node-fetch@^1.0.1:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
+node-forge@^0.6.20:
+  version "0.6.49"
+  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.49.tgz#f1ee95d5d74623938fe19d698aa5a26d54d2f60f"
+  integrity sha1-8e6V1ddGI5OP4Z1piqWibVTS9g8=
+
 node-int64@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -7002,13 +6828,6 @@ path-parse@^1.0.5, path-parse@^1.0.6:
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
 
-path-to-regexp@^1.7.0:
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
-  integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
-  dependencies:
-    isarray "0.0.1"
-
 path-type@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -7109,6 +6928,13 @@ png-chunks-extract@^1.0.0:
   dependencies:
     crc-32 "^0.3.0"
 
+polyfill-promise@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/polyfill-promise/-/polyfill-promise-4.0.1.tgz#f8448dc27c3b967d5f67fc060f56ed64e2286b49"
+  integrity sha1-+ESNwnw7ln1fZ/wGD1btZOIoa0k=
+  dependencies:
+    bluebird "^2.9.27"
+
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -7245,16 +7071,6 @@ pretty-format@^23.6.0:
     ansi-regex "^3.0.0"
     ansi-styles "^3.2.0"
 
-pretty-format@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
-  integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==
-  dependencies:
-    "@jest/types" "^24.9.0"
-    ansi-regex "^4.0.0"
-    ansi-styles "^3.2.0"
-    react-is "^16.8.4"
-
 private@^0.1.6, private@^0.1.8:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -7536,7 +7352,7 @@ react-immutable-proptypes@^2.1.0:
   resolved "https://registry.yarnpkg.com/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz#023d6f39bb15c97c071e9e60d00d136eac5fa0b4"
   integrity sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ=
 
-react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
+react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
   version "16.12.0"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
   integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
@@ -8094,11 +7910,6 @@ safe-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-samsam@1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
-  integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==
-
 sane@^2.0.0:
   version "2.5.2"
   resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
@@ -8235,24 +8046,16 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
-sinon@^5.0.7:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.1.1.tgz#19c59810ffb733ea6e76a28b94a71fc4c2f523b8"
-  integrity sha512-h/3uHscbt5pQNxkf7Y/Lb9/OM44YNCicHakcq73ncbrIS8lXg+ZGOZbtuU+/km4YnyiCYfQQEwANaReJz7KDfw==
-  dependencies:
-    "@sinonjs/formatio" "^2.0.0"
-    diff "^3.5.0"
-    lodash.get "^4.4.2"
-    lolex "^2.4.2"
-    nise "^1.3.3"
-    supports-color "^5.4.0"
-    type-detect "^4.0.8"
-
 sisteransi@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
   integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
 
+sjcl@^1.0.3:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
+  integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
+
 slash@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
@@ -8888,6 +8691,18 @@ stylelint@^9.10.1:
     svg-tags "^1.0.0"
     table "^5.0.0"
 
+subtle@^0.1.8:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/subtle/-/subtle-0.1.8.tgz#0c12599b9cf13127eda11626510cd8f24f878916"
+  integrity sha1-DBJZm5zxMSftoRYmUQzY8k+HiRY=
+  dependencies:
+    ecc-jsbn "0.0.1"
+    node-forge "^0.6.20"
+    polyfill-promise "^4.0.1"
+    sjcl "^1.0.3"
+  optionalDependencies:
+    ecc-qj "git+https://github.com/rynomad/ecc.git"
+
 sugarss@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
@@ -8928,7 +8743,7 @@ supports-color@^4.5.0:
   dependencies:
     has-flag "^2.0.0"
 
-supports-color@^5.3.0, supports-color@^5.4.0:
+supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
   integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@@ -9216,11 +9031,6 @@ type-check@~0.3.2:
   dependencies:
     prelude-ls "~1.1.2"
 
-type-detect@4.0.8, type-detect@^4.0.8:
-  version "4.0.8"
-  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
-  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-
 type-is@~1.6.17:
   version "1.6.18"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"

From 0041dae664c04809981975116959057446cb534d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 16 Dec 2019 11:55:01 +0000
Subject: [PATCH 13/86] 26 test failures to go :D

---
 package.json                                  |  2 +
 .../structures/MessagePanel-test.js           |  5 ++-
 test/components/structures/auth/Login-test.js |  2 +-
 .../structures/auth/Registration-test.js      |  2 +-
 test/stores/RoomViewStore-test.js             |  2 +-
 test/utils/MegolmExportEncryption-test.js     | 24 ++++++++++-
 yarn.lock                                     | 43 +++++++++++++++++--
 7 files changed, 70 insertions(+), 10 deletions(-)

diff --git a/package.json b/package.json
index b21b2cedac..f3f10a86ca 100644
--- a/package.json
+++ b/package.json
@@ -154,6 +154,7 @@
     "matrix-mock-request": "^1.2.3",
     "matrix-react-test-utils": "^0.2.2",
     "mocha": "^5.0.5",
+    "node-webcrypto-shim": "^0.0.1",
     "react-test-renderer": "^16.9.0",
     "require-json": "0.0.1",
     "rimraf": "^2.4.3",
@@ -163,6 +164,7 @@
     "stylelint-scss": "^3.9.0",
     "subtle": "^0.1.8",
     "walk": "^2.3.9",
+    "webcrypto": "^0.1.1",
     "webpack": "^4.20.2",
     "webpack-cli": "^3.1.1"
   }
diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js
index 88abaf6735..c64ae9680a 100644
--- a/test/components/structures/MessagePanel-test.js
+++ b/test/components/structures/MessagePanel-test.js
@@ -78,8 +78,9 @@ describe('MessagePanel', function() {
         client.credentials = {userId: '@me:here'};
 
         // HACK: We assume all settings want to be disabled
-        SettingsStore.getValue = jest.fn().returns(false);
-        SettingsStore.getValue.withArgs('showDisplaynameChanges').returns(true);
+        SettingsStore.getValue = jest.fn((arg) => {
+            return arg === "showDisplaynameChanges";
+        });
 
         // This option clobbers the duration of all animations to be 1ms
         // which makes unit testing a lot simpler (the animation doesn't
diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js
index 3520672cbe..7ca210ff93 100644
--- a/test/components/structures/auth/Login-test.js
+++ b/test/components/structures/auth/Login-test.js
@@ -69,7 +69,7 @@ describe('Login', function() {
     });
 
     it('should show form without change server link when custom URLs disabled', function() {
-        jest.spyOn(SdkConfig, "get").returns({
+        jest.spyOn(SdkConfig, "get").mockReturnValue({
             disable_custom_urls: true,
         });
 
diff --git a/test/components/structures/auth/Registration-test.js b/test/components/structures/auth/Registration-test.js
index 12f736640e..bf26763a79 100644
--- a/test/components/structures/auth/Registration-test.js
+++ b/test/components/structures/auth/Registration-test.js
@@ -58,7 +58,7 @@ describe('Registration', function() {
     });
 
     it('should show form when custom URLs disabled', function() {
-        jest.spyOn(SdkConfig, "get").returns({
+        jest.spyOn(SdkConfig, "get").mockReturnValue({
             disable_custom_urls: true,
         });
 
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index 249af84885..1d92a02562 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -27,7 +27,7 @@ describe('RoomViewStore', function() {
     });
 
     it('can be used to view a room by alias and join', function(done) {
-        peg.get().getRoomIdForAlias.returns(Promise.resolve({room_id: "!randomcharacters:aser.ver"}));
+        peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"});
         peg.get().joinRoom = (roomAddress) => {
             expect(roomAddress).toBe("#somealias2:aser.ver");
             done();
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index 0973f75a31..0df68c8bfb 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -16,7 +16,27 @@ limitations under the License.
 
 "use strict";
 
-import SubtleCrypto from 'subtle';
+import webcrypto from "node-webcrypto-shim";
+import {TextEncoder} from "util";
+import crypto from "crypto";
+
+function getRandomValues(buf) {
+    if (!(buf instanceof Uint8Array)) {
+        throw new TypeError('expected Uint8Array');
+    }
+    if (buf.length > 65536) {
+        const e = new Error();
+        e.code = 22;
+        e.message = 'Failed to execute \'getRandomValues\' on \'Crypto\': The ' +
+            'ArrayBufferView\'s byte length (' + buf.length + ') exceeds the ' +
+            'number of bytes of entropy available via this API (65536).';
+        e.name = 'QuotaExceededError';
+        throw e;
+    }
+    const bytes = crypto.randomBytes(buf.length);
+    buf.set(bytes);
+    return buf;
+}
 
 const TEST_VECTORS=[
     [
@@ -66,7 +86,7 @@ describe('MegolmExportEncryption', function() {
     let MegolmExportEncryption;
 
     beforeAll(() => {
-        window.crypto = { subtle: SubtleCrypto };
+        window.crypto = { ...webcrypto, getRandomValues };
         MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
     });
 
diff --git a/yarn.lock b/yarn.lock
index 61a8c49591..44b630ea89 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2343,7 +2343,7 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
     shebang-command "^1.2.0"
     which "^1.2.9"
 
-crypto-browserify@^3.11.0:
+crypto-browserify@^3.10.0, crypto-browserify@^3.11.0:
   version "3.12.0"
   resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
   integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
@@ -2562,6 +2562,11 @@ detect-newline@^2.1.0:
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
   integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
 
+detect-node@^2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
+  integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
+
 di@^0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -6200,7 +6205,7 @@ nan@^1.6.2:
   resolved "https://registry.yarnpkg.com/nan/-/nan-1.9.0.tgz#1a9cd2755609766f5c291e4194fce39fde286515"
   integrity sha1-GpzSdVYJdm9cKR5BlPzjn94oZRU=
 
-nan@^2.12.1:
+nan@^2.12.1, nan@^2.13.2:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
   integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
@@ -6341,6 +6346,23 @@ node-releases@^1.1.41:
   dependencies:
     semver "^6.3.0"
 
+node-webcrypto-ossl@^1.0.31:
+  version "1.0.48"
+  resolved "https://registry.yarnpkg.com/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.48.tgz#640e9547f8ae1d0becc8374a65e1d0e11ab385ea"
+  integrity sha512-MWUkQ/5wrs7lpAr+fhsLMfjdxKGd3dQFVqWbNMkyYyCMRW8E7ScailqtCZYDLTnJtU6B+91rXxCJNyZvbYaSOg==
+  dependencies:
+    mkdirp "^0.5.1"
+    nan "^2.13.2"
+    tslib "^1.9.3"
+    webcrypto-core "^0.1.26"
+
+node-webcrypto-shim@^0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/node-webcrypto-shim/-/node-webcrypto-shim-0.0.1.tgz#674167cfb688c3a9cc5b1650b89b11395080f31a"
+  integrity sha512-8MBE1nDPpJ5IMM48K98EZ6UZavN/Y3P2SKkmux9Pr8RkQNCy3ahVOayjSE8g6/EGpN5w6nT+Vj9RvZ8iXY6HxQ==
+  dependencies:
+    node-webcrypto-ossl "^1.0.31"
+
 nopt@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@@ -8995,7 +9017,7 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-tslib@^1.8.1, tslib@^1.9.0:
+tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
@@ -9401,6 +9423,21 @@ watchpack@^1.6.0:
     graceful-fs "^4.1.2"
     neo-async "^2.5.0"
 
+webcrypto-core@^0.1.26:
+  version "0.1.26"
+  resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-0.1.26.tgz#977e5cdd9173db6ac8b18414d66ee3759a8b1024"
+  integrity sha512-BZVgJZkkHyuz8loKvsaOKiBDXDpmMZf5xG4QAOlSeYdXlFUl9c1FRrVnAXcOdb4fTHMG+TRu81odJwwSfKnWTA==
+  dependencies:
+    tslib "^1.7.1"
+
+webcrypto@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/webcrypto/-/webcrypto-0.1.1.tgz#63316e5ecbce6ce965ab5f259c2faa62c3e782b4"
+  integrity sha512-BAvoatS38TbHdyt42ECLroi27NmDh5iea5l5rHC6nZTZjlbJlndrT0FoIiEq7fmPHpmNtP0lMFKVMEKZQFIrGA==
+  dependencies:
+    crypto-browserify "^3.10.0"
+    detect-node "^2.0.3"
+
 webidl-conversions@^4.0.2:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"

From b8faaa23c12003c174631ebd01a403a0b1af64e1 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 16 Dec 2019 16:06:43 -0700
Subject: [PATCH 14/86] Remove irrelevant targets

---
 .babelrc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.babelrc b/.babelrc
index 3710e20a37..7e50f4a757 100644
--- a/.babelrc
+++ b/.babelrc
@@ -5,8 +5,7 @@
             "targets": {
                 "browsers": [
                     "last 2 versions"
-                ],
-                "node": 12
+                ]
             },
             "modules": "commonjs"
         }],

From 434570eca962d5894627a3acb799ff618cdc61b0 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 16 Dec 2019 16:07:58 -0700
Subject: [PATCH 15/86] Explain why MatrixClientPeg is the way it is

---
 src/MatrixClientPeg.js | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 4d293b7e34..46debab731 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -247,5 +247,10 @@ class _MatrixClientPeg {
 if (!global.mxMatrixClientPeg) {
     global.mxMatrixClientPeg = new _MatrixClientPeg();
 }
+
+// We export both because the syntax is slightly different with
+// our babel changes. We maintain both for backwards compatibility
+// and for babel to be happy.
+// TODO: Convert this to a single export
 export default global.mxMatrixClientPeg;
 export const MatrixClientPeg = global.mxMatrixClientPeg;

From 0a9985fb489dc33863f03cb883d00589827f013c Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 16 Dec 2019 16:10:11 -0700
Subject: [PATCH 16/86] Rename decorator for clarity

---
 src/components/views/auth/AuthPage.js                      | 4 ++--
 src/utils/{replaceComponent.ts => replaceableComponent.ts} | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
 rename src/utils/{replaceComponent.ts => replaceableComponent.ts} (89%)

diff --git a/src/components/views/auth/AuthPage.js b/src/components/views/auth/AuthPage.js
index 8448df9ac8..bfac6514e2 100644
--- a/src/components/views/auth/AuthPage.js
+++ b/src/components/views/auth/AuthPage.js
@@ -18,9 +18,9 @@ limitations under the License.
 
 import React from 'react';
 import sdk from '../../../index';
-import {replaceComponent} from "../../../utils/replaceComponent";
+import {replaceableComponent} from "../../../utils/replaceableComponent";
 
-@replaceComponent("views.auth.AuthPage")
+@replaceableComponent("views.auth.AuthPage")
 export default class AuthPage extends React.PureComponent {
     render() {
         const AuthFooter = sdk.getComponent('auth.AuthFooter');
diff --git a/src/utils/replaceComponent.ts b/src/utils/replaceableComponent.ts
similarity index 89%
rename from src/utils/replaceComponent.ts
rename to src/utils/replaceableComponent.ts
index 1775c42294..a52d71ba6d 100644
--- a/src/utils/replaceComponent.ts
+++ b/src/utils/replaceableComponent.ts
@@ -17,6 +17,6 @@ limitations under the License.
 import React from 'react';
 import sdk from '../index';
 
-export function replaceComponent(name: string, origComponent: React.Component) {
+export function replaceableComponent(name: string, origComponent: React.Component) {
     return () => sdk.getComponent(name) || origComponent;
 }

From 9865ce899bdf75c6e28e068b740e94ca762e373c Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 16 Dec 2019 16:34:46 -0700
Subject: [PATCH 17/86] Add a bunch of docs

We're making an assumption here that the decorator is actually all over the app when it's not.
---
 README.md                         |  1 +
 docs/skinning.md                  | 71 +++++++++++++++++++++++++++++++
 src/utils/replaceableComponent.ts | 18 ++++++++
 3 files changed, 90 insertions(+)
 create mode 100644 docs/skinning.md

diff --git a/README.md b/README.md
index 1265c2bd77..aefbeb9964 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@ practices that anyone working with the SDK needs to be be aware of and uphold:
 
   * After creating a new component you must run `yarn reskindex` to regenerate
     the `component-index.js` for the SDK (used in future for skinning)
+    <!-- TODO: Remove this once this approach to skinning is replaced -->
 
   * The view's CSS file MUST have the same name (e.g. view/rooms/MessageTile.css).
     CSS for matrix-react-sdk currently resides in
diff --git a/docs/skinning.md b/docs/skinning.md
new file mode 100644
index 0000000000..229bc78372
--- /dev/null
+++ b/docs/skinning.md
@@ -0,0 +1,71 @@
+# Skinning
+
+The react-sdk can be skinned to replace presentation components, CSS, or
+other relevant parts of the SDK. Typically consumers will replace entire
+components and get the ability for custom CSS as a result.
+
+This doc isn't exhaustive on how skinning works, though it should cover
+some of the more complicated parts such as component replacement.
+
+## Loading a skin
+
+1. Generate a `component-index.js` (preferably using the tools that the react-sdk
+exposes). This can typically be done with a npm script like `"reskindex -h src/header"`.
+2. In your app's entry point, add something like this code:
+   ```javascript
+   import {loadSkin} from "matrix-react-sdk";
+   loadSkin(import("component-index").components);
+   // The rest of your imports go under this.
+   ```
+3. Import the remainder of the SDK and bootstrap your app.
+
+It is extremely important that you **do not** import anything else from the
+SDK prior to loading your skin as otherwise the skin might not work. Loading
+the skin should be one of the first things your app does, if not the very
+first thing.
+
+Additionally, **do not** provide `loadSkin` with the react-sdk components
+themselves otherwise the app might explode. The SDK is already aware of its
+components and doesn't need to be told.
+
+## Replacing components
+
+Components that replace the react-sdk ones MUST have a `replaces` static
+key on the component's class to describe which component it overrides. For
+example, if your `VectorAuthPage` component is meant to replace the react-sdk
+`AuthPage` component then you'd add `static replaces = 'views.auth.AuthPage';`
+to the `VectorAuthPage` class.
+
+Other than that, the skin just needs to be loaded normally as mentioned above.
+Consumers of the SDK likely will not be interested in the rest of this section.
+
+### SDK developer notes
+
+Components in the react-sdk MUST be decorated with the `@replaceableComponent`
+function. For components that can't use the decorator, they must use a
+variation that provides similar functionality. The decorator gives consumers
+an opportunity to load skinned components by abusing import ordering and 
+behaviour.
+
+Decorators are executed at import time which is why we can abuse the import
+ordering behaviour: importing `loadSkin` doesn't trigger any components to
+be imported, allowing the consumer to specify a skin. When the consumer does
+import a component (for example, `MatrixChat`), it starts to pull in all the
+components via `import` statements. When the components get pulled in the
+decorator checks with the skinned components to see if it should be replacing
+the component being imported. The decorator then effectively replaces the
+components when needed by specifying the skinned component as an override for
+the SDK's component, which should in theory override critical functions like
+`render()` and lifecycle event handlers. 
+
+The decorator also means that older usage of `getComponent()` is no longer
+required because components should be replaced by the decorator. Eventually
+the react-sdk should only have one usage of `getComponent()`: the decorator.
+
+The decorator assumes that if `getComponent()` returns null that there is
+no skinned version of the component and continues on using the SDK's component.
+In previous versions of the SDK, the function would throw an error instead
+because it also expected the skin to list the SDK's components as well, however
+that is no longer possible due to the above.
+
+In short, components should always be `import`ed.
diff --git a/src/utils/replaceableComponent.ts b/src/utils/replaceableComponent.ts
index a52d71ba6d..4777e2f395 100644
--- a/src/utils/replaceableComponent.ts
+++ b/src/utils/replaceableComponent.ts
@@ -17,6 +17,24 @@ limitations under the License.
 import React from 'react';
 import sdk from '../index';
 
+/**
+ * Replaces a component with a skinned version if a skinned version exists.
+ * This decorator should only be applied to components which can be skinned. For
+ * the react-sdk this means all components should be decorated with this.
+ *
+ * The decoration works by assuming the skin has been loaded prior to the
+ * decorator being called. If that's not the case, the developer will find
+ * out quickly through various amounts of errors and explosions.
+ *
+ * For a bit more detail on how this works, see docs/skinning.md
+ * @param {string} name The dot-path name of the component being replaced.
+ * @param {React.Component} origComponent The component that can be replaced
+ * with a skinned version. If no skinned version is available, this component
+ * will be used.
+ */
 export function replaceableComponent(name: string, origComponent: React.Component) {
+    // Decorators return a function to override the class (origComponent). This
+    // ultimately assumes that `getComponent()` won't throw an error and instead
+    // return a falsey value like `null` when the skin doesn't have a component.
     return () => sdk.getComponent(name) || origComponent;
 }

From ab3fb6581b9b662da21750100565d29f1dd18c22 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 11:24:37 +0000
Subject: [PATCH 18/86] Down to 7 test failures

---
 __mocks__/browser-request.js                  | 16 ++++
 __mocks__/imageMock.js                        |  1 +
 package.json                                  |  8 +-
 src/utils/MegolmExportEncryption.js           |  2 +-
 test/Terms-test.js                            |  8 +-
 test/components/structures/GroupView-test.js  | 12 +--
 .../structures/MessagePanel-test.js           |  4 +-
 .../dialogs/InteractiveAuthDialog-test.js     |  6 +-
 .../elements/MemberEventListSummary-test.js   | 26 +++---
 .../views/groups/GroupMemberList-test.js      |  4 +-
 test/i18n-test/languageHandler-test.js        |  3 +
 test/mock-clock.js                            |  2 +-
 test/utils/MegolmExportEncryption-test.js     | 28 ++----
 yarn.lock                                     | 93 +++++++++++--------
 14 files changed, 122 insertions(+), 91 deletions(-)
 create mode 100644 __mocks__/browser-request.js
 create mode 100644 __mocks__/imageMock.js

diff --git a/__mocks__/browser-request.js b/__mocks__/browser-request.js
new file mode 100644
index 0000000000..45f83a1763
--- /dev/null
+++ b/__mocks__/browser-request.js
@@ -0,0 +1,16 @@
+const en = require("../src/i18n/strings/en_EN");
+
+module.exports = jest.fn((opts, cb) => {
+    if (opts.url.endsWith("languages.json")) {
+        cb(undefined, {status: 200}, JSON.stringify({
+            "en": {
+                "fileName": "en_EN.json",
+                "label": "English",
+            },
+        }));
+    } else if (opts.url.endsWith("en_EN.json")) {
+        cb(undefined, {status: 200}, JSON.stringify(en));
+    } else {
+        cb(undefined, {status: 404}, "");
+    }
+});
diff --git a/__mocks__/imageMock.js b/__mocks__/imageMock.js
new file mode 100644
index 0000000000..474ac702b4
--- /dev/null
+++ b/__mocks__/imageMock.js
@@ -0,0 +1 @@
+module.exports = "image-file-stub";
diff --git a/package.json b/package.json
index f3f10a86ca..6424f28ac8 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,7 @@
     "zxcvbn": "^4.4.2"
   },
   "devDependencies": {
+    "@peculiar/webcrypto": "^1.0.22",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "^10.0.1",
@@ -154,7 +155,6 @@
     "matrix-mock-request": "^1.2.3",
     "matrix-react-test-utils": "^0.2.2",
     "mocha": "^5.0.5",
-    "node-webcrypto-shim": "^0.0.1",
     "react-test-renderer": "^16.9.0",
     "require-json": "0.0.1",
     "rimraf": "^2.4.3",
@@ -164,8 +164,12 @@
     "stylelint-scss": "^3.9.0",
     "subtle": "^0.1.8",
     "walk": "^2.3.9",
-    "webcrypto": "^0.1.1",
     "webpack": "^4.20.2",
     "webpack-cli": "^3.1.1"
+  },
+  "jest": {
+    "moduleNameMapper": {
+      "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"
+    }
   }
 }
diff --git a/src/utils/MegolmExportEncryption.js b/src/utils/MegolmExportEncryption.js
index 2f2fc4cca7..bc9af8db78 100644
--- a/src/utils/MegolmExportEncryption.js
+++ b/src/utils/MegolmExportEncryption.js
@@ -130,7 +130,7 @@ export async function decryptMegolmKeyFile(data, password) {
  * @param {String} data
  * @param {String} password
  * @param {Object=} options
- * @param {Nunber=} options.kdf_rounds Number of iterations to perform of the
+ * @param {Number=} options.kdf_rounds Number of iterations to perform of the
  *    key-derivation function.
  * @return {Promise<ArrayBuffer>} promise for encrypted output
  */
diff --git a/test/Terms-test.js b/test/Terms-test.js
index 71daafddfe..e644e0dbbb 100644
--- a/test/Terms-test.js
+++ b/test/Terms-test.js
@@ -154,10 +154,10 @@ describe('Terms', function() {
 
         const interactionCallback = jest.fn().mockResolvedValue(["http://example.com/one", "http://example.com/two"]);
         await startTermsFlow([IM_SERVICE_ONE, IM_SERVICE_TWO], interactionCallback);
-        // console.log("getTerms call 0", MatrixClientPeg.get().getTerms.getCall(0).args);
-        // console.log("getTerms call 1", MatrixClientPeg.get().getTerms.getCall(1).args);
-        // console.log("interactionCallback call", interactionCallback.getCall(0).args);
-        // console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.getCall(0).args);
+        console.log("getTerms call 0", MatrixClientPeg.get().getTerms.mock.calls[0]);
+        console.log("getTerms call 1", MatrixClientPeg.get().getTerms.mock.calls[1]);
+        console.log("interactionCallback call", interactionCallback.mock.calls[0]);
+        console.log("agreeToTerms call", MatrixClientPeg.get().agreeToTerms.mock.calls[0]);
 
         expect(interactionCallback).toBeCalledWith([
             {
diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index 57531a427c..31e7c26c9a 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -191,13 +191,13 @@ describe('GroupView', function() {
             const name = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_GroupView_header_name');
             const nameElement = ReactDOM.findDOMNode(name);
             expect(nameElement).toBeTruthy();
-            expect(nameElement.innerText).toContain('The name of a community');
-            expect(nameElement.innerText).toContain(groupId);
+            expect(nameElement.textContent).toContain('The name of a community');
+            expect(nameElement.textContent).toContain(groupId);
 
             const shortDesc = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_GroupView_header_shortDesc');
             const shortDescElement = ReactDOM.findDOMNode(shortDesc);
             expect(shortDescElement).toBeTruthy();
-            expect(shortDescElement.innerText).toBe('This is a community');
+            expect(shortDescElement.textContent).toBe('This is a community');
         });
 
         httpBackend.when('GET', '/groups/' + groupIdEncoded + '/summary').respond(200, summaryResponse);
@@ -217,7 +217,7 @@ describe('GroupView', function() {
             const longDesc = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_GroupView_groupDesc');
             const longDescElement = ReactDOM.findDOMNode(longDesc);
             expect(longDescElement).toBeTruthy();
-            expect(longDescElement.innerText).toBe('This is a LONG description.');
+            expect(longDescElement.textContent).toBe('This is a LONG description.');
             expect(longDescElement.innerHTML).toBe('<div dir="auto">This is a <b>LONG</b> description.</div>');
         });
 
@@ -331,7 +331,7 @@ describe('GroupView', function() {
             const roomDetailListRoomNameElement = ReactDOM.findDOMNode(roomDetailListRoomName);
 
             expect(roomDetailListRoomNameElement).toBeTruthy();
-            expect(roomDetailListRoomNameElement.innerText).toEqual('Some room name');
+            expect(roomDetailListRoomNameElement.textContent).toEqual('Some room name');
         });
 
         httpBackend.when('GET', '/groups/' + groupIdEncoded + '/summary').respond(200, summaryResponse);
@@ -362,7 +362,7 @@ describe('GroupView', function() {
             const shortDesc = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_GroupView_header_shortDesc');
             const shortDescElement = ReactDOM.findDOMNode(shortDesc);
             expect(shortDescElement).toBeTruthy();
-            expect(shortDescElement.innerText).toBe('This is a community');
+            expect(shortDescElement.textContent).toBe('This is a community');
         });
 
         httpBackend.when('GET', '/groups/' + groupIdEncoded + '/summary').respond(200, summaryResponse);
diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js
index c64ae9680a..5d70554b07 100644
--- a/test/components/structures/MessagePanel-test.js
+++ b/test/components/structures/MessagePanel-test.js
@@ -31,8 +31,8 @@ const MessagePanel = sdk.getComponent('structures.MessagePanel');
 import MatrixClientPeg from '../../../src/MatrixClientPeg';
 import Matrix from 'matrix-js-sdk';
 
-const test_utils = require('test-utils');
-const mockclock = require('mock-clock');
+const test_utils = require('../../test-utils');
+const mockclock = require('../../mock-clock');
 
 import Velocity from 'velocity-animate';
 
diff --git a/test/components/views/dialogs/InteractiveAuthDialog-test.js b/test/components/views/dialogs/InteractiveAuthDialog-test.js
index fe7f538d7d..b047d6073b 100644
--- a/test/components/views/dialogs/InteractiveAuthDialog-test.js
+++ b/test/components/views/dialogs/InteractiveAuthDialog-test.js
@@ -91,8 +91,8 @@ describe('InteractiveAuthDialog', function() {
             expect(submitNode.disabled).toBe(false);
             ReactTestUtils.Simulate.submit(formNode, {});
 
-            expect(doRequest.callCount).toEqual(1);
-            expect(doRequest.calledWithMatch({
+            expect(doRequest).toHaveBeenCalledTimes(1);
+            expect(doRequest).toBeCalledWith(expect.objectContaining({
                 session: "sess",
                 type: "m.login.password",
                 password: "s3kr3t",
@@ -100,7 +100,7 @@ describe('InteractiveAuthDialog', function() {
                     type: "m.id.user",
                     user: "@user:id",
                 },
-            })).toBe(true);
+            }));
             // let the request complete
             return sleep(1);
         }).then(() => {
diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js
index e068a8e749..3f4c7da951 100644
--- a/test/components/views/elements/MemberEventListSummary-test.js
+++ b/test/components/views/elements/MemberEventListSummary-test.js
@@ -157,7 +157,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe("user_1 joined and left and joined");
     });
@@ -193,7 +193,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe("user_1 joined and left 7 times");
     });
@@ -241,7 +241,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 was unbanned, joined and left 7 times and was invited",
@@ -294,7 +294,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 was unbanned, joined and left 2 times, was banned, " +
@@ -353,7 +353,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 and one other were unbanned, joined and left 2 times and were banned",
@@ -391,7 +391,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_0 and 19 others were unbanned, joined and left 2 times and were banned",
@@ -442,7 +442,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " +
@@ -516,7 +516,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 was invited, was banned, joined, rejected their invitation, left, " +
@@ -563,7 +563,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 and one other rejected their invitations and " +
@@ -599,7 +599,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 rejected their invitation 2 times",
@@ -627,7 +627,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1 and user_2 joined 2 times",
@@ -654,7 +654,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_1, user_2 and one other joined",
@@ -679,7 +679,7 @@ describe('MemberEventListSummary', function() {
         const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
             instance, "mx_EventListSummary_summary",
         );
-        const summaryText = summary.innerText;
+        const summaryText = summary.textContent;
 
         expect(summaryText).toBe(
             "user_0, user_1 and 18 others joined",
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index 08f0f781ac..2b20ce0067 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -112,7 +112,7 @@ describe("GroupMemberList", function() {
             const memberList = ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList_joined");
             const memberListElement = ReactDOM.findDOMNode(memberList);
             expect(memberListElement).toBeTruthy();
-            expect(memberListElement.innerText).toBe("Test");
+            expect(memberListElement.textContent).toBe("Test");
         });
 
         httpBackend.when("GET", "/groups/" + groupIdEncoded + "/summary").respond(200, summaryResponse);
@@ -132,7 +132,7 @@ describe("GroupMemberList", function() {
             const memberList = ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList_joined");
             const memberListElement = ReactDOM.findDOMNode(memberList);
             expect(memberListElement).toBeTruthy();
-            expect(memberListElement.innerText).toBe("Failed to load group members");
+            expect(memberListElement.textContent).toBe("Failed to load group members");
         });
 
         httpBackend.when("GET", "/groups/" + groupIdEncoded + "/summary").respond(200, summaryResponse);
diff --git a/test/i18n-test/languageHandler-test.js b/test/i18n-test/languageHandler-test.js
index 36dc4bed87..fa6969b715 100644
--- a/test/i18n-test/languageHandler-test.js
+++ b/test/i18n-test/languageHandler-test.js
@@ -9,6 +9,9 @@ describe('languageHandler', function() {
         testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
+        languageHandler.setMissingEntryGenerator(function(key) {
+            return key.split('|', 2)[1];
+        });
     });
 
     it('translates a string to german', function() {
diff --git a/test/mock-clock.js b/test/mock-clock.js
index 103e186c1f..d9eac1a0e1 100644
--- a/test/mock-clock.js
+++ b/test/mock-clock.js
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * jasmine-core and exposed as a standalone module. The interface is just the
  * same as that of jasmine.clock. For example:
  *
- *    var mock_clock = require("mock-clock").clock();
+ *    var mock_clock = require("../../mock-clock").clock();
  *    mock_clock.install();
  *    setTimeout(function() {
  *        timerCallback();
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index 0df68c8bfb..b3a9782ce6 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -16,26 +16,14 @@ limitations under the License.
 
 "use strict";
 
-import webcrypto from "node-webcrypto-shim";
 import {TextEncoder} from "util";
-import crypto from "crypto";
+import nodeCrypto from "crypto";
+import { Crypto } from "@peculiar/webcrypto";
+
+const webCrypto = new Crypto();
 
 function getRandomValues(buf) {
-    if (!(buf instanceof Uint8Array)) {
-        throw new TypeError('expected Uint8Array');
-    }
-    if (buf.length > 65536) {
-        const e = new Error();
-        e.code = 22;
-        e.message = 'Failed to execute \'getRandomValues\' on \'Crypto\': The ' +
-            'ArrayBufferView\'s byte length (' + buf.length + ') exceeds the ' +
-            'number of bytes of entropy available via this API (65536).';
-        e.name = 'QuotaExceededError';
-        throw e;
-    }
-    const bytes = crypto.randomBytes(buf.length);
-    buf.set(bytes);
-    return buf;
+    return nodeCrypto.randomFillSync(buf);
 }
 
 const TEST_VECTORS=[
@@ -86,7 +74,8 @@ describe('MegolmExportEncryption', function() {
     let MegolmExportEncryption;
 
     beforeAll(() => {
-        window.crypto = { ...webcrypto, getRandomValues };
+        // window.crypto = { subtle: crypto.subtle, getRandomValues };
+        window.crypto = { subtle: webCrypto.subtle, getRandomValues };
         MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
     });
 
@@ -130,7 +119,8 @@ cissyYBxjsfsAn
             });
         });
 
-        it('should decrypt a range of inputs', function(done) {
+        // TODO find a subtlecrypto shim which doesn't break this test
+        it.skip('should decrypt a range of inputs', function(done) {
             function next(i) {
                 if (i >= TEST_VECTORS.length) {
                     done();
diff --git a/yarn.lock b/yarn.lock
index 44b630ea89..1aa34972f2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -138,6 +138,33 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
+"@peculiar/asn1-schema@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-1.0.3.tgz#e55ff9e98a1cf31832629aabacf85be3edf13a48"
+  integrity sha512-Tfgj9eNJ6cTKEtEuidKenLHMx/Q5M8KEE9hnohHqvdpqHJXWYr5RlT3GjAHPjGXy5+mr7sSfuXfzE6aAkEGN7A==
+  dependencies:
+    asn1js "^2.0.22"
+    tslib "^1.9.3"
+
+"@peculiar/json-schema@^1.1.6":
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.6.tgz#134096ede59cf502e9acbdb24cbe55eb97ad2fe9"
+  integrity sha512-A8DM0ueA+LUqD/HuNPHDd8yMkhbRmnV0iosxyB/uOV1cfiKlCKXDeqkzHTOZpveRI05iCjZxqkPZ2+Nnw1wB4A==
+  dependencies:
+    tslib "^1.10.0"
+
+"@peculiar/webcrypto@^1.0.22":
+  version "1.0.22"
+  resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.0.22.tgz#9dae652fce6bacd9df15bc91965797cee33adf67"
+  integrity sha512-NP6H6ZGXUvJnQJCWzUgnRcQv+9nMCNwLUDhTwOxRUwPFvtHauMOl0oPTKUjbhInCMaE55gJqB4yc0YKbde6Exw==
+  dependencies:
+    "@peculiar/asn1-schema" "^1.0.3"
+    "@peculiar/json-schema" "^1.1.6"
+    asn1js "^2.0.26"
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
+    webcrypto-core "^1.0.17"
+
 "@types/events@*":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -644,6 +671,13 @@ asn1@~0.2.3:
   dependencies:
     safer-buffer "~2.1.0"
 
+asn1js@^2.0.22, asn1js@^2.0.26:
+  version "2.0.26"
+  resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-2.0.26.tgz#0a6d435000f556a96c6012969d9704d981b71251"
+  integrity sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==
+  dependencies:
+    pvutils latest
+
 assert-plus@1.0.0, assert-plus@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
@@ -2343,7 +2377,7 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
     shebang-command "^1.2.0"
     which "^1.2.9"
 
-crypto-browserify@^3.10.0, crypto-browserify@^3.11.0:
+crypto-browserify@^3.11.0:
   version "3.12.0"
   resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
   integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
@@ -2562,11 +2596,6 @@ detect-newline@^2.1.0:
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
   integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
 
-detect-node@^2.0.3:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
-  integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
-
 di@^0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -6205,7 +6234,7 @@ nan@^1.6.2:
   resolved "https://registry.yarnpkg.com/nan/-/nan-1.9.0.tgz#1a9cd2755609766f5c291e4194fce39fde286515"
   integrity sha1-GpzSdVYJdm9cKR5BlPzjn94oZRU=
 
-nan@^2.12.1, nan@^2.13.2:
+nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
   integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
@@ -6346,23 +6375,6 @@ node-releases@^1.1.41:
   dependencies:
     semver "^6.3.0"
 
-node-webcrypto-ossl@^1.0.31:
-  version "1.0.48"
-  resolved "https://registry.yarnpkg.com/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.48.tgz#640e9547f8ae1d0becc8374a65e1d0e11ab385ea"
-  integrity sha512-MWUkQ/5wrs7lpAr+fhsLMfjdxKGd3dQFVqWbNMkyYyCMRW8E7ScailqtCZYDLTnJtU6B+91rXxCJNyZvbYaSOg==
-  dependencies:
-    mkdirp "^0.5.1"
-    nan "^2.13.2"
-    tslib "^1.9.3"
-    webcrypto-core "^0.1.26"
-
-node-webcrypto-shim@^0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/node-webcrypto-shim/-/node-webcrypto-shim-0.0.1.tgz#674167cfb688c3a9cc5b1650b89b11395080f31a"
-  integrity sha512-8MBE1nDPpJ5IMM48K98EZ6UZavN/Y3P2SKkmux9Pr8RkQNCy3ahVOayjSE8g6/EGpN5w6nT+Vj9RvZ8iXY6HxQ==
-  dependencies:
-    node-webcrypto-ossl "^1.0.31"
-
 nopt@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@@ -7222,6 +7234,18 @@ punycode@^2.1.0, punycode@^2.1.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
+pvtsutils@^1.0.9:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.0.9.tgz#0eb6106f27878ccaa55e7dfbf6bd2c75af461dee"
+  integrity sha512-/kDsuCKPqJuIzn37w6+iN+TiSrN+zrwPEd7FjT61oNbRvceGdsS94fMEWZ4/h6QZU5EZhBMiV+79IYedroP/Yw==
+  dependencies:
+    tslib "^1.10.0"
+
+pvutils@latest:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
+  integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
+
 qjobs@^1.1.4:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
@@ -9017,7 +9041,7 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
@@ -9423,20 +9447,13 @@ watchpack@^1.6.0:
     graceful-fs "^4.1.2"
     neo-async "^2.5.0"
 
-webcrypto-core@^0.1.26:
-  version "0.1.26"
-  resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-0.1.26.tgz#977e5cdd9173db6ac8b18414d66ee3759a8b1024"
-  integrity sha512-BZVgJZkkHyuz8loKvsaOKiBDXDpmMZf5xG4QAOlSeYdXlFUl9c1FRrVnAXcOdb4fTHMG+TRu81odJwwSfKnWTA==
+webcrypto-core@^1.0.17:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.0.17.tgz#a9354bc0b1ba6735e882f4137ede2c4366e6ad9b"
+  integrity sha512-7jxTLgtM+TahBPErx/Dd2XvxFDfWJrHxjVeTSvIa4LSgiYrmCPlC2INiAMAfb8MbtHiwJKKqF5sPS0AWNjBbXw==
   dependencies:
-    tslib "^1.7.1"
-
-webcrypto@^0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/webcrypto/-/webcrypto-0.1.1.tgz#63316e5ecbce6ce965ab5f259c2faa62c3e782b4"
-  integrity sha512-BAvoatS38TbHdyt42ECLroi27NmDh5iea5l5rHC6nZTZjlbJlndrT0FoIiEq7fmPHpmNtP0lMFKVMEKZQFIrGA==
-  dependencies:
-    crypto-browserify "^3.10.0"
-    detect-node "^2.0.3"
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
 
 webidl-conversions@^4.0.2:
   version "4.0.2"

From e6d8487302609a0f1148bfd1199e40a765d572ad Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 11:47:01 +0000
Subject: [PATCH 19/86] Fix more tests

---
 package.json                                  |  12 +-
 .../views/settings/KeyBackupPanel.js          |   2 +-
 .../elements/MemberEventListSummary-test.js   |   7 +-
 .../views/groups/GroupMemberList-test.js      |   1 +
 .../components/views/rooms/MemberList-test.js |   2 +-
 test/components/views/rooms/RoomList-test.js  |   4 +-
 .../views/rooms/RoomSettings-test.js          |   3 +-
 test/i18n-test/languageHandler-test.js        |   4 +-
 test/setupTests.js                            |   4 +
 test/stores/RoomViewStore-test.js             |   4 +-
 yarn.lock                                     | 883 +-----------------
 11 files changed, 42 insertions(+), 884 deletions(-)
 create mode 100644 test/setupTests.js

diff --git a/package.json b/package.json
index 6424f28ac8..05129cb7c0 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,6 @@
     "git-revision.txt",
     "header",
     "jenkins.sh",
-    "karma.conf.js",
     "lib",
     "package.json",
     "release.sh",
@@ -143,18 +142,8 @@
     "file-loader": "^3.0.1",
     "flow-parser": "^0.57.3",
     "jest": "^23.2.0",
-    "karma": "^4.0.1",
-    "karma-chrome-launcher": "^2.2.0",
-    "karma-cli": "^1.0.1",
-    "karma-logcapture-reporter": "0.0.1",
-    "karma-mocha": "^1.3.0",
-    "karma-sourcemap-loader": "^0.3.7",
-    "karma-spec-reporter": "^0.0.31",
-    "karma-summary-reporter": "^1.5.1",
-    "karma-webpack": "^4.0.0-beta.0",
     "matrix-mock-request": "^1.2.3",
     "matrix-react-test-utils": "^0.2.2",
-    "mocha": "^5.0.5",
     "react-test-renderer": "^16.9.0",
     "require-json": "0.0.1",
     "rimraf": "^2.4.3",
@@ -168,6 +157,7 @@
     "webpack-cli": "^3.1.1"
   },
   "jest": {
+    "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
       "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"
     }
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js
index 559b1e0ba1..5f0b2ea55d 100644
--- a/src/components/views/settings/KeyBackupPanel.js
+++ b/src/components/views/settings/KeyBackupPanel.js
@@ -21,7 +21,7 @@ import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
-import SettingsStore from '../../../../lib/settings/SettingsStore';
+import SettingsStore from '../../../settings/SettingsStore';
 import { accessSecretStorage } from '../../../CrossSigningManager';
 
 export default class KeyBackupPanel extends React.PureComponent {
diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js
index 3f4c7da951..a68c39eeeb 100644
--- a/test/components/views/elements/MemberEventListSummary-test.js
+++ b/test/components/views/elements/MemberEventListSummary-test.js
@@ -84,13 +84,8 @@ describe('MemberEventListSummary', function() {
         return eventsForUsers;
     };
 
-    beforeEach(function(done) {
+    beforeEach(function() {
         testUtils.stubClient();
-
-        languageHandler.setLanguage('en').then(done);
-        languageHandler.setMissingEntryGenerator(function(key) {
-            return key.split('|', 2)[1];
-        });
     });
 
     it('renders expanded events if there are less than props.threshold', function() {
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index 2b20ce0067..fd96c9f331 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -24,6 +24,7 @@ import sdk from "../../../skinned-sdk";
 import Matrix from "matrix-js-sdk";
 
 import * as TestUtils from "../../../test-utils";
+import * as languageHandler from "../../../../src/languageHandler";
 const { waitForUpdate } = TestUtils;
 
 const GroupMemberList = sdk.getComponent("views.groups.GroupMemberList");
diff --git a/test/components/views/rooms/MemberList-test.js b/test/components/views/rooms/MemberList-test.js
index bc12041398..06b596691d 100644
--- a/test/components/views/rooms/MemberList-test.js
+++ b/test/components/views/rooms/MemberList-test.js
@@ -5,7 +5,7 @@ import lolex from 'lolex';
 
 import * as TestUtils from '../../../test-utils';
 
-import sdk from '../../../../src/index';
+import sdk from '../../../skinned-sdk';
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
 
 import {Room, RoomMember, User} from 'matrix-js-sdk';
diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js
index 446abede3d..737ac579f4 100644
--- a/test/components/views/rooms/RoomList-test.js
+++ b/test/components/views/rooms/RoomList-test.js
@@ -5,7 +5,7 @@ import lolex from 'lolex';
 
 import * as TestUtils from '../../../test-utils';
 
-import sdk from '../../../../src/index';
+import sdk from '../../../skinned-sdk';
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
 import { DragDropContext } from 'react-beautiful-dnd';
 
@@ -177,7 +177,7 @@ describe('RoomList', () => {
 
     function itDoesCorrectOptimisticUpdatesForDraggedRoomTiles() {
         // TODO: Re-enable dragging tests when we support dragging again.
-        xdescribe('does correct optimistic update when dragging from', () => {
+        describe.skip('does correct optimistic update when dragging from', () => {
             it('rooms to people', () => {
                 expectCorrectMove(undefined, 'im.vector.fake.direct');
             });
diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js
index 7b7c554a2c..a89508fe98 100644
--- a/test/components/views/rooms/RoomSettings-test.js
+++ b/test/components/views/rooms/RoomSettings-test.js
@@ -4,12 +4,13 @@ import ReactDOM from 'react-dom';
 import jest from 'jest-mock';
 import * as testUtils from '../../../test-utils';
 import sdk from '../../../skinned-sdk';
-const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
 import MatrixClientPeg from '../../../../src/MatrixClientPeg';
 import SettingsStore from '../../../../src/settings/SettingsStore';
 
 
 describe.skip('RoomSettings', () => {
+    const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
+
     let parentDiv = null;
     let client = null;
     let roomSettings = null;
diff --git a/test/i18n-test/languageHandler-test.js b/test/i18n-test/languageHandler-test.js
index fa6969b715..7968186e9e 100644
--- a/test/i18n-test/languageHandler-test.js
+++ b/test/i18n-test/languageHandler-test.js
@@ -9,9 +9,7 @@ describe('languageHandler', function() {
         testUtils.stubClient();
 
         languageHandler.setLanguage('en').then(done);
-        languageHandler.setMissingEntryGenerator(function(key) {
-            return key.split('|', 2)[1];
-        });
+        languageHandler.setMissingEntryGenerator(key => key.split("|", 2)[1]);
     });
 
     it('translates a string to german', function() {
diff --git a/test/setupTests.js b/test/setupTests.js
new file mode 100644
index 0000000000..9c2d16a8df
--- /dev/null
+++ b/test/setupTests.js
@@ -0,0 +1,4 @@
+import * as languageHandler from "../src/languageHandler";
+
+languageHandler.setLanguage('en');
+languageHandler.setMissingEntryGenerator(key => key.split("|", 2)[1]);
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index 1d92a02562..83ec3d9c2e 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -16,7 +16,7 @@ describe('RoomViewStore', function() {
     });
 
     it('can be used to view a room by ID and join', function(done) {
-        peg.get().joinRoom = (roomAddress) => {
+        peg.get().joinRoom = async (roomAddress) => {
             expect(roomAddress).toBe("!randomcharacters:aser.ver");
             done();
         };
@@ -28,7 +28,7 @@ describe('RoomViewStore', function() {
 
     it('can be used to view a room by alias and join', function(done) {
         peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"});
-        peg.get().joinRoom = (roomAddress) => {
+        peg.get().joinRoom = async (roomAddress) => {
             expect(roomAddress).toBe("#somealias2:aser.ver");
             done();
         };
diff --git a/yarn.lock b/yarn.lock
index 1aa34972f2..7ea9ea5b24 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -403,14 +403,6 @@ abbrev@1:
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
 
-accepts@~1.3.4:
-  version "1.3.7"
-  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
-  integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
-  dependencies:
-    mime-types "~2.1.24"
-    negotiator "0.6.2"
-
 acorn-globals@^4.1.0:
   version "4.3.4"
   resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
@@ -439,11 +431,6 @@ acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.1:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
   integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==
 
-after@0.8.2:
-  version "0.8.2"
-  resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
-  integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-
 agent-base@4, agent-base@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@@ -490,11 +477,6 @@ another-json@^0.2.0:
   resolved "https://registry.yarnpkg.com/another-json/-/another-json-0.2.0.tgz#b5f4019c973b6dd5c6506a2d93469cb6d32aeedc"
   integrity sha1-tfQBnJc7bdXGUGotk0acttMq7tw=
 
-ansi-colors@^3.0.0:
-  version "3.2.4"
-  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
-  integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-
 ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
@@ -543,14 +525,6 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-anymatch@~3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
-  integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
-  dependencies:
-    normalize-path "^3.0.0"
-    picomatch "^2.0.4"
-
 append-transform@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
@@ -640,11 +614,6 @@ array-unique@^0.3.2:
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
   integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
 
-arraybuffer.slice@~0.0.7:
-  version "0.0.7"
-  resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
-  integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
-
 arrify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -711,7 +680,7 @@ async-limiter@~1.0.0:
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
   integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
 
-async@^2.1.4, async@^2.5.0, async@^2.6.2:
+async@^2.1.4, async@^2.5.0:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
   integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
@@ -1485,11 +1454,6 @@ babylon@^6.18.0:
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
   integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
 
-backo2@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
-  integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
-
 bail@^1.0.0:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.4.tgz#7181b66d508aa3055d3f6c13f0a0c720641dde9b"
@@ -1507,21 +1471,11 @@ base-x@^3.0.2:
   dependencies:
     safe-buffer "^5.0.1"
 
-base64-arraybuffer@0.1.5:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
-  integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
-
 base64-js@^1.0.2:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
   integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
 
-base64id@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
-  integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=
-
 base@^0.11.1:
   version "0.11.2"
   resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@@ -1542,13 +1496,6 @@ bcrypt-pbkdf@^1.0.0:
   dependencies:
     tweetnacl "^0.14.3"
 
-better-assert@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
-  integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=
-  dependencies:
-    callsite "1.0.0"
-
 big.js@^5.2.2:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -1559,22 +1506,12 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
-binary-extensions@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
-  integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
-
-blob@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
-  integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
-
 bluebird@^2.9.27:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
   integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
 
-bluebird@^3.3.0, bluebird@^3.5.0, bluebird@^3.5.5:
+bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
@@ -1589,22 +1526,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
   integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
 
-body-parser@^1.16.1:
-  version "1.19.0"
-  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
-  integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
-  dependencies:
-    bytes "3.1.0"
-    content-type "~1.0.4"
-    debug "2.6.9"
-    depd "~1.1.2"
-    http-errors "1.7.2"
-    iconv-lite "0.4.24"
-    on-finished "~2.3.0"
-    qs "6.7.0"
-    raw-body "2.4.0"
-    type-is "~1.6.17"
-
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -1638,13 +1559,6 @@ braces@^2.3.1, braces@^2.3.2:
     split-string "^3.0.2"
     to-regex "^3.0.1"
 
-braces@^3.0.2, braces@~3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
-  integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
-  dependencies:
-    fill-range "^7.0.1"
-
 brorand@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@@ -1672,11 +1586,6 @@ browser-resolve@^1.11.3:
   dependencies:
     resolve "1.1.7"
 
-browser-stdout@1.3.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
-  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
-
 browserify-aes@^1.0.0, browserify-aes@^1.0.4:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
@@ -1759,24 +1668,6 @@ bser@2.1.1:
   dependencies:
     node-int64 "^0.4.0"
 
-buffer-alloc-unsafe@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
-  integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-
-buffer-alloc@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
-  integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
-  dependencies:
-    buffer-alloc-unsafe "^1.1.0"
-    buffer-fill "^1.0.0"
-
-buffer-fill@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
-  integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
-
 buffer-from@^1.0.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -1801,11 +1692,6 @@ builtin-status-codes@^3.0.0:
   resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
   integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
 
-bytes@3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
-  integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
 cacache@^12.0.0, cacache@^12.0.2:
   version "12.0.3"
   resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
@@ -1861,11 +1747,6 @@ caller-path@^2.0.0:
   dependencies:
     caller-callsite "^2.0.0"
 
-callsite@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
-  integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
-
 callsites@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
@@ -1922,7 +1803,7 @@ chain-function@^1.0.0:
   resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc"
   integrity sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==
 
-chalk@2.4.2, "chalk@^1.1.3 || 2.x", chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2002,21 +1883,6 @@ chokidar@^2.0.2, chokidar@^2.1.2:
   optionalDependencies:
     fsevents "^1.2.7"
 
-chokidar@^3.0.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6"
-  integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==
-  dependencies:
-    anymatch "~3.1.1"
-    braces "~3.0.2"
-    glob-parent "~5.1.0"
-    is-binary-path "~2.1.0"
-    is-glob "~4.0.1"
-    normalize-path "~3.0.0"
-    readdirp "~3.2.0"
-  optionalDependencies:
-    fsevents "~2.1.1"
-
 chownr@^1.1.1:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
@@ -2087,15 +1953,6 @@ cliui@^5.0.0:
     strip-ansi "^5.2.0"
     wrap-ansi "^5.1.0"
 
-clone-deep@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
-  integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
-  dependencies:
-    is-plain-object "^2.0.4"
-    kind-of "^6.0.2"
-    shallow-clone "^3.0.0"
-
 clone-regexp@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f"
@@ -2139,11 +1996,6 @@ color-name@1.1.3:
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
   integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
 
-colors@^1.1.0, colors@^1.1.2:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
-  integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-
 combined-stream@^1.0.6, combined-stream@~1.0.6:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -2151,11 +2003,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
   dependencies:
     delayed-stream "~1.0.0"
 
-commander@2.15.1:
-  version "2.15.1"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
-  integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
-
 commander@^2.11.0, commander@^2.20.0, commander@~2.20.3:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -2176,26 +2023,11 @@ commonmark@^0.28.1:
     minimist "~ 1.2.0"
     string.prototype.repeat "^0.2.0"
 
-component-bind@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
-  integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=
-
-component-emitter@1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
-  integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
-
 component-emitter@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
   integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
 
-component-inherit@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-  integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
-
 concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2226,16 +2058,6 @@ concurrently@^4.0.1:
     tree-kill "^1.2.1"
     yargs "^12.0.5"
 
-connect@^3.6.0:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
-  integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
-  dependencies:
-    debug "2.6.9"
-    finalhandler "1.1.2"
-    parseurl "~1.3.3"
-    utils-merge "1.0.1"
-
 console-browserify@^1.1.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
@@ -2251,7 +2073,7 @@ constants-browserify@^1.0.0:
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
   integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
 
-content-type@^1.0.2, content-type@~1.0.4:
+content-type@^1.0.2:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
@@ -2263,11 +2085,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1,
   dependencies:
     safe-buffer "~5.1.1"
 
-cookie@0.3.1:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
-  integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
-
 copy-concurrently@^1.0.0:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
@@ -2418,11 +2235,6 @@ currently-unhandled@^0.4.1:
   dependencies:
     array-find-index "^1.0.1"
 
-custom-event@~1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
-  integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
-
 cyclist@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@@ -2449,31 +2261,26 @@ date-fns@^1.30.1:
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
   integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
 
-date-format@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
-  integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==
-
 date-names@^0.1.11:
   version "0.1.13"
   resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.13.tgz#c4358f6f77c8056e2f5ea68fdbb05f0bf1e53bd0"
   integrity sha512-IxxoeD9tdx8pXVcmqaRlPvrXIsSrSrIZzfzlOkm9u+hyzKp5Wk/odt9O/gd7Ockzy8n/WHeEpTVJ2bF3mMV4LA==
 
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
-  version "2.6.9"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
-  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
-  dependencies:
-    ms "2.0.0"
-
-debug@3.1.0, debug@~3.1.0:
+debug@3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
   integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
   dependencies:
     ms "2.0.0"
 
-debug@^3.0.0, debug@^3.1.0, debug@^3.2.6:
+debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.1.0, debug@^3.2.6:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
   integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -2561,11 +2368,6 @@ delegates@^1.0.0:
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
   integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
 
-depd@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
-  integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
 des.js@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
@@ -2596,11 +2398,6 @@ detect-newline@^2.1.0:
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
   integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
 
-di@^0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
-  integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
-
 diff-dom@^4.1.3:
   version "4.1.6"
   resolved "https://registry.yarnpkg.com/diff-dom/-/diff-dom-4.1.6.tgz#ecd20f4b34703d777b7956790fc7e28e5ff3fece"
@@ -2614,7 +2411,7 @@ diff-match-patch@^1.0.4:
   resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
   integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
 
-diff@3.5.0, diff@^3.2.0:
+diff@^3.2.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
@@ -2661,16 +2458,6 @@ dom-helpers@^3.2.0:
   dependencies:
     "@babel/runtime" "^7.1.2"
 
-dom-serialize@^2.2.0:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
-  integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=
-  dependencies:
-    custom-event "~1.0.0"
-    ent "~2.2.0"
-    extend "^3.0.0"
-    void-elements "^2.0.0"
-
 dom-serializer@0:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@@ -2754,11 +2541,6 @@ ecc-jsbn@~0.1.1:
   dependencies:
     nan "^1.6.2"
 
-ee-first@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
-  integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
 electron-to-chromium@^1.3.317:
   version "1.3.322"
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
@@ -2802,11 +2584,6 @@ emojis-list@^2.0.0:
   resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
   integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
 
-encodeurl@~1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
-  integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-
 encoding@^0.1.11:
   version "0.1.12"
   resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
@@ -2821,46 +2598,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
-engine.io-client@~3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36"
-  integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==
-  dependencies:
-    component-emitter "1.2.1"
-    component-inherit "0.0.3"
-    debug "~3.1.0"
-    engine.io-parser "~2.1.1"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    ws "~3.3.1"
-    xmlhttprequest-ssl "~1.5.4"
-    yeast "0.1.2"
-
-engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6"
-  integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==
-  dependencies:
-    after "0.8.2"
-    arraybuffer.slice "~0.0.7"
-    base64-arraybuffer "0.1.5"
-    blob "0.0.5"
-    has-binary2 "~1.0.2"
-
-engine.io@~3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2"
-  integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==
-  dependencies:
-    accepts "~1.3.4"
-    base64id "1.0.0"
-    cookie "0.3.1"
-    debug "~3.1.0"
-    engine.io-parser "~2.1.0"
-    ws "~3.3.1"
-
 enhanced-resolve@4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
@@ -2879,11 +2616,6 @@ enhanced-resolve@^4.1.0:
     memory-fs "^0.5.0"
     tapable "^1.0.0"
 
-ent@~2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
-  integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
 entities@^1.1.1, "entities@~ 1.1.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@@ -2980,12 +2712,12 @@ es6-promisify@^5.0.0:
   dependencies:
     es6-promise "^4.0.3"
 
-escape-html@^1.0.3, escape-html@~1.0.3:
+escape-html@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -3187,11 +2919,6 @@ esutils@^2.0.2:
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
   integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
 
-eventemitter3@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
-  integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
-
 events@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@@ -3504,26 +3231,6 @@ fill-range@^4.0.0:
     repeat-string "^1.6.1"
     to-regex-range "^2.1.0"
 
-fill-range@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
-  integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
-  dependencies:
-    to-regex-range "^5.0.1"
-
-finalhandler@1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
-  integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
-  dependencies:
-    debug "2.6.9"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    on-finished "~2.3.0"
-    parseurl "~1.3.3"
-    statuses "~1.5.0"
-    unpipe "~1.0.0"
-
 find-cache-dir@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
@@ -3637,13 +3344,6 @@ focus-visible@^5.0.2:
   resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.0.2.tgz#4fae9cf40458b73c10701c9774c462e3ccd53caf"
   integrity sha512-zT2fj/bmOgEBjqGbURGlowTmCwsIs3bRDMr/sFZz8Ly7VkEiwuCn9swNTL3pPuf8Oua2de7CLuKdnuNajWdDsQ==
 
-follow-redirects@^1.0.0:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f"
-  integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==
-  dependencies:
-    debug "^3.0.0"
-
 for-in@^1.0.1, for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -3690,22 +3390,6 @@ from2@^2.1.0:
     inherits "^2.0.1"
     readable-stream "^2.0.0"
 
-fs-access@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
-  integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=
-  dependencies:
-    null-check "^1.0.0"
-
-fs-extra@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
-  integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
-  dependencies:
-    graceful-fs "^4.1.2"
-    jsonfile "^4.0.0"
-    universalify "^0.1.0"
-
 fs-minipass@^1.2.5:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
@@ -3749,11 +3433,6 @@ fsevents@^1.2.3:
     nan "^2.12.1"
     node-pre-gyp "^0.12.0"
 
-fsevents@~2.1.1:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
-  integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
-
 function-bind@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -3866,13 +3545,6 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
 
-glob-parent@~5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
-  integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==
-  dependencies:
-    is-glob "^4.0.1"
-
 glob-to-regexp@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
@@ -3883,18 +3555,6 @@ glob-to-regexp@^0.4.1:
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
   integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
 
-glob@7.1.2:
-  version "7.1.2"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
-  integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.4"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
 glob@^5.0.14:
   version "5.0.15"
   resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
@@ -3990,16 +3650,11 @@ gonzales-pe@^4.2.3:
   dependencies:
     minimist "1.1.x"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
   integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
 
-growl@1.10.5:
-  version "1.10.5"
-  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
-  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
-
 growly@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -4036,18 +3691,6 @@ has-ansi@^2.0.0:
   dependencies:
     ansi-regex "^2.0.0"
 
-has-binary2@~1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
-  integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==
-  dependencies:
-    isarray "2.0.1"
-
-has-cors@1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
-  integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
-
 has-flag@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
@@ -4127,11 +3770,6 @@ hash.js@^1.0.0, hash.js@^1.0.3:
     inherits "^2.0.3"
     minimalistic-assert "^1.0.1"
 
-he@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
-  integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
-
 highlight.js@^9.15.8:
   version "9.16.2"
   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e"
@@ -4209,17 +3847,6 @@ http-cache-semantics@^3.8.1:
   resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
   integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
 
-http-errors@1.7.2:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
-  integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
-  dependencies:
-    depd "~1.1.2"
-    inherits "2.0.3"
-    setprototypeof "1.1.1"
-    statuses ">= 1.5.0 < 2"
-    toidentifier "1.0.0"
-
 http-proxy-agent@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@@ -4228,15 +3855,6 @@ http-proxy-agent@^2.1.0:
     agent-base "4"
     debug "3.1.0"
 
-http-proxy@^1.13.0:
-  version "1.18.0"
-  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
-  integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
-  dependencies:
-    eventemitter3 "^4.0.0"
-    follow-redirects "^1.0.0"
-    requires-port "^1.0.0"
-
 http-signature@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@@ -4502,13 +4120,6 @@ is-binary-path@^1.0.0:
   dependencies:
     binary-extensions "^1.0.0"
 
-is-binary-path@~2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
-  integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
-  dependencies:
-    binary-extensions "^2.0.0"
-
 is-boolean-object@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93"
@@ -4689,7 +4300,7 @@ is-glob@^3.1.0:
   dependencies:
     is-extglob "^2.1.0"
 
-is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
+is-glob@^4.0.0, is-glob@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
   integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@@ -4747,11 +4358,6 @@ is-number@^4.0.0:
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
   integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
 
-is-number@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
-  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
 is-obj@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@@ -4873,23 +4479,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
 
-isarray@2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
-  integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
-
 isarray@^2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
   integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
 
-isbinaryfile@^3.0.0:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80"
-  integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==
-  dependencies:
-    buffer-alloc "^1.2.0"
-
 isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -5443,13 +5037,6 @@ json5@^2.1.0:
   dependencies:
     minimist "^1.2.0"
 
-jsonfile@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
-  integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
-  optionalDependencies:
-    graceful-fs "^4.1.6"
-
 jsprim@^1.2.2:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -5468,98 +5055,6 @@ jsx-ast-utils@^2.2.3:
     array-includes "^3.0.3"
     object.assign "^4.1.0"
 
-karma-chrome-launcher@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
-  integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==
-  dependencies:
-    fs-access "^1.0.0"
-    which "^1.2.1"
-
-karma-cli@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-1.0.1.tgz#ae6c3c58a313a1d00b45164c455b9b86ce17f960"
-  integrity sha1-rmw8WKMTodALRRZMRVubhs4X+WA=
-  dependencies:
-    resolve "^1.1.6"
-
-karma-logcapture-reporter@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/karma-logcapture-reporter/-/karma-logcapture-reporter-0.0.1.tgz#bf1b0b1c915e0de295a15fe2f0179d4281bacddc"
-  integrity sha1-vxsLHJFeDeKVoV/i8BedQoG6zdw=
-
-karma-mocha@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-1.3.0.tgz#eeaac7ffc0e201eb63c467440d2b69c7cf3778bf"
-  integrity sha1-7qrH/8DiAetjxGdEDStpx883eL8=
-  dependencies:
-    minimist "1.2.0"
-
-karma-sourcemap-loader@^0.3.7:
-  version "0.3.7"
-  resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8"
-  integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=
-  dependencies:
-    graceful-fs "^4.1.2"
-
-karma-spec-reporter@^0.0.31:
-  version "0.0.31"
-  resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3"
-  integrity sha1-SDDccUihVcfXoYbmMjOaDYD63sM=
-  dependencies:
-    colors "^1.1.2"
-
-karma-summary-reporter@^1.5.1:
-  version "1.7.1"
-  resolved "https://registry.yarnpkg.com/karma-summary-reporter/-/karma-summary-reporter-1.7.1.tgz#ff751e6e3950a3b3f2ae96a39b10fdc87938c4db"
-  integrity sha512-1I1njfSKFwogQrfDDyjyXKUeysYdD7SXoXBz2o7oK7RpiGsteyBoV3+6J5qFLcT0D8VGxLzYCsU0BbyeeHIl0g==
-  dependencies:
-    chalk "^1.1.3 || 2.x"
-
-karma-webpack@^4.0.0-beta.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.2.tgz#23219bd95bdda853e3073d3874d34447c77bced0"
-  integrity sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==
-  dependencies:
-    clone-deep "^4.0.1"
-    loader-utils "^1.1.0"
-    neo-async "^2.6.1"
-    schema-utils "^1.0.0"
-    source-map "^0.7.3"
-    webpack-dev-middleware "^3.7.0"
-
-karma@^4.0.1:
-  version "4.4.1"
-  resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.1.tgz#6d9aaab037a31136dc074002620ee11e8c2e32ab"
-  integrity sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==
-  dependencies:
-    bluebird "^3.3.0"
-    body-parser "^1.16.1"
-    braces "^3.0.2"
-    chokidar "^3.0.0"
-    colors "^1.1.0"
-    connect "^3.6.0"
-    di "^0.0.1"
-    dom-serialize "^2.2.0"
-    flatted "^2.0.0"
-    glob "^7.1.1"
-    graceful-fs "^4.1.2"
-    http-proxy "^1.13.0"
-    isbinaryfile "^3.0.0"
-    lodash "^4.17.14"
-    log4js "^4.0.0"
-    mime "^2.3.1"
-    minimatch "^3.0.2"
-    optimist "^0.6.1"
-    qjobs "^1.1.4"
-    range-parser "^1.2.0"
-    rimraf "^2.6.0"
-    safe-buffer "^5.0.1"
-    socket.io "2.1.1"
-    source-map "^0.6.1"
-    tmp "0.0.33"
-    useragent "2.3.0"
-
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -5748,17 +5243,6 @@ log-symbols@^2.0.0, log-symbols@^2.2.0:
   dependencies:
     chalk "^2.0.1"
 
-log4js@^4.0.0:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5"
-  integrity sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==
-  dependencies:
-    date-format "^2.0.0"
-    debug "^4.1.1"
-    flatted "^2.0.0"
-    rfdc "^1.1.4"
-    streamroller "^1.0.6"
-
 loglevel@^1.6.4:
   version "1.6.6"
   resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312"
@@ -5789,14 +5273,6 @@ loud-rejection@^1.0.0:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
 
-lru-cache@4.1.x:
-  version "4.1.5"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
-  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
-  dependencies:
-    pseudomap "^1.0.2"
-    yallist "^2.1.2"
-
 lru-cache@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -5944,11 +5420,6 @@ mdast-util-compact@^1.0.0:
   resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
   integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
 
-media-typer@0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
-  integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
 mem@^4.0.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
@@ -6072,18 +5543,13 @@ mime-db@1.42.0:
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
   integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
 
-mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24:
+mime-types@^2.1.12, mime-types@~2.1.19:
   version "2.1.25"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437"
   integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==
   dependencies:
     mime-db "1.42.0"
 
-mime@^2.3.1, mime@^2.4.4:
-  version "2.4.4"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
-  integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
-
 mimic-fn@^1.0.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
@@ -6104,7 +5570,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
 
-"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -6178,30 +5644,13 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
+mkdirp@^0.5.0, mkdirp@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
   dependencies:
     minimist "0.0.8"
 
-mocha@^5.0.5:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
-  integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
-  dependencies:
-    browser-stdout "1.3.1"
-    commander "2.15.1"
-    debug "3.1.0"
-    diff "3.5.0"
-    escape-string-regexp "1.0.5"
-    glob "7.1.2"
-    growl "1.10.5"
-    he "1.1.1"
-    minimatch "3.0.4"
-    mkdirp "0.5.1"
-    supports-color "5.4.0"
-
 move-concurrently@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -6270,11 +5719,6 @@ needle@^2.2.1:
     iconv-lite "^0.4.4"
     sax "^1.2.4"
 
-negotiator@0.6.2:
-  version "0.6.2"
-  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
-  integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-
 neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
@@ -6400,7 +5844,7 @@ normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
   dependencies:
     remove-trailing-separator "^1.0.1"
 
-normalize-path@^3.0.0, normalize-path@~3.0.0:
+normalize-path@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
   integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
@@ -6445,11 +5889,6 @@ npmlog@^4.0.2:
     gauge "~2.7.3"
     set-blocking "~2.0.0"
 
-null-check@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
-  integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
-
 num2fraction@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
@@ -6475,11 +5914,6 @@ object-assign@^4.1.0, object-assign@^4.1.1:
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
   integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
 
-object-component@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
-  integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=
-
 object-copy@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
@@ -6569,13 +6003,6 @@ object.values@^1.1.0:
     function-bind "^1.1.1"
     has "^1.0.3"
 
-on-finished@~2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
-  integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
-  dependencies:
-    ee-first "1.1.1"
-
 once@^1.3.0, once@^1.3.1, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -6791,25 +6218,6 @@ parse5@4.0.0:
   resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
   integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
 
-parseqs@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
-  integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=
-  dependencies:
-    better-assert "~1.0.0"
-
-parseuri@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
-  integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=
-  dependencies:
-    better-assert "~1.0.0"
-
-parseurl@~1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
-  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-
 pascalcase@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@@ -6899,11 +6307,6 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-picomatch@^2.0.4:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
-  integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
-
 pify@^2.0.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -7167,11 +6570,6 @@ prr@~1.0.1:
   resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
   integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
 
-pseudomap@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
-  integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
 psl@^1.1.24:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.5.0.tgz#47fd1292def7fdb1e138cd78afa8814cebcf7b13"
@@ -7246,11 +6644,6 @@ pvutils@latest:
   resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
   integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
 
-qjobs@^1.1.4:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
-  integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
-
 qr.js@0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
@@ -7263,11 +6656,6 @@ qrcode-react@^0.1.16:
   dependencies:
     qr.js "0.0.0"
 
-qs@6.7.0:
-  version "6.7.0"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
-  integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
 qs@^6.5.2, qs@^6.6.0:
   version "6.9.1"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
@@ -7329,21 +6717,6 @@ randomfill@^1.0.3:
     randombytes "^2.0.5"
     safe-buffer "^5.1.0"
 
-range-parser@^1.2.0, range-parser@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
-  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-
-raw-body@2.4.0:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
-  integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
-  dependencies:
-    bytes "3.1.0"
-    http-errors "1.7.2"
-    iconv-lite "0.4.24"
-    unpipe "1.0.0"
-
 rc@1.2.8, rc@^1.2.7, rc@^1.2.8:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -7534,13 +6907,6 @@ readdirp@^2.0.0, readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
-readdirp@~3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839"
-  integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==
-  dependencies:
-    picomatch "^2.0.4"
-
 realpath-native@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
@@ -7788,11 +7154,6 @@ require-main-filename@^2.0.0:
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
   integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
 
-requires-port@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
-  integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-
 reselect@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
@@ -7838,7 +7199,7 @@ resolve@1.1.7:
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
   integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
@@ -7863,11 +7224,6 @@ retry@^0.10.0:
   resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
   integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
 
-rfdc@^1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
-  integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-
 rimraf@2.6.3:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@@ -7875,7 +7231,7 @@ rimraf@2.6.3:
   dependencies:
     glob "^7.1.3"
 
-rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.3:
+rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -8050,11 +7406,6 @@ setimmediate@^1.0.4, setimmediate@^1.0.5:
   resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
   integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
 
-setprototypeof@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
-  integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
 sha.js@^2.4.0, sha.js@^2.4.8:
   version "2.4.11"
   resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
@@ -8063,13 +7414,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
-shallow-clone@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
-  integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
-  dependencies:
-    kind-of "^6.0.2"
-
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -8243,52 +7587,6 @@ snapdragon@^0.8.1:
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
-socket.io-adapter@~1.1.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9"
-  integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==
-
-socket.io-client@2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f"
-  integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==
-  dependencies:
-    backo2 "1.0.2"
-    base64-arraybuffer "0.1.5"
-    component-bind "1.0.0"
-    component-emitter "1.2.1"
-    debug "~3.1.0"
-    engine.io-client "~3.2.0"
-    has-binary2 "~1.0.2"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    object-component "0.0.3"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    socket.io-parser "~3.2.0"
-    to-array "0.1.4"
-
-socket.io-parser@~3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077"
-  integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==
-  dependencies:
-    component-emitter "1.2.1"
-    debug "~3.1.0"
-    isarray "2.0.1"
-
-socket.io@2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980"
-  integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==
-  dependencies:
-    debug "~3.1.0"
-    engine.io "~3.2.0"
-    has-binary2 "~1.0.2"
-    socket.io-adapter "~1.1.0"
-    socket.io-client "2.1.1"
-    socket.io-parser "~3.2.0"
-
 socks-proxy-agent@^4.0.0:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
@@ -8359,11 +7657,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 
-source-map@^0.7.3:
-  version "0.7.3"
-  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
-  integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
-
 spawn-command@^0.0.2-1:
   version "0.0.2-1"
   resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
@@ -8465,11 +7758,6 @@ static-extend@^0.1.1:
     define-property "^0.2.5"
     object-copy "^0.1.0"
 
-"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
-  integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
 stealthy-require@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
@@ -8507,17 +7795,6 @@ stream-shift@^1.0.0:
   resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
   integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
 
-streamroller@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
-  integrity sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==
-  dependencies:
-    async "^2.6.2"
-    date-format "^2.0.0"
-    debug "^3.2.6"
-    fs-extra "^7.0.1"
-    lodash "^4.17.14"
-
 string-length@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
@@ -8756,13 +8033,6 @@ sugarss@^2.0.0:
   dependencies:
     postcss "^7.0.2"
 
-supports-color@5.4.0:
-  version "5.4.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
-  integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
-  dependencies:
-    has-flag "^3.0.0"
-
 supports-color@6.1.0, supports-color@^6.1.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
@@ -8919,7 +8189,7 @@ tmatch@^2.0.1:
   resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf"
   integrity sha1-DFYkbzPzDaG409colauvFmYPOM8=
 
-tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
+tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
   integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
@@ -8931,11 +8201,6 @@ tmpl@1.0.x:
   resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
   integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
 
-to-array@0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
-  integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
-
 to-arraybuffer@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@@ -8966,13 +8231,6 @@ to-regex-range@^2.1.0:
     is-number "^3.0.0"
     repeat-string "^1.6.1"
 
-to-regex-range@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
-  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
-  dependencies:
-    is-number "^7.0.0"
-
 to-regex@^3.0.1, to-regex@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@@ -8983,11 +8241,6 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
-toidentifier@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
-  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
 tough-cookie@^2.3.3, tough-cookie@^2.3.4:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -9077,14 +8330,6 @@ type-check@~0.3.2:
   dependencies:
     prelude-ls "~1.1.2"
 
-type-is@~1.6.17:
-  version "1.6.18"
-  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
-  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
-  dependencies:
-    media-typer "0.3.0"
-    mime-types "~2.1.24"
-
 type-of@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/type-of/-/type-of-2.0.1.tgz#e72a1741896568e9f628378d816d6912f7f23972"
@@ -9108,11 +8353,6 @@ uglify-js@^3.1.4:
     commander "~2.20.3"
     source-map "~0.6.1"
 
-ultron@~1.1.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
-  integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
-
 unherit@^1.0.4:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.2.tgz#14f1f397253ee4ec95cec167762e77df83678449"
@@ -9214,16 +8454,6 @@ unist-util-visit@^1.1.0:
   dependencies:
     unist-util-visit-parents "^2.0.0"
 
-universalify@^0.1.0:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
-  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-unpipe@1.0.0, unpipe@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
-  integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
 unset-value@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@@ -9283,14 +8513,6 @@ user-home@^1.1.1:
   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
   integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA=
 
-useragent@2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
-  integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==
-  dependencies:
-    lru-cache "4.1.x"
-    tmp "0.0.x"
-
 util-deprecate@^1.0.1, util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -9318,11 +8540,6 @@ util@^0.11.0:
   dependencies:
     inherits "2.0.3"
 
-utils-merge@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
-  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-
 uuid@^3.3.2:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
@@ -9397,11 +8614,6 @@ vm-browserify@^1.0.1:
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
   integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
 
-void-elements@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
-  integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-
 w3c-hr-time@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
@@ -9477,25 +8689,6 @@ webpack-cli@^3.1.1:
     v8-compile-cache "2.0.3"
     yargs "13.2.4"
 
-webpack-dev-middleware@^3.7.0:
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
-  integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
-  dependencies:
-    memory-fs "^0.4.1"
-    mime "^2.4.4"
-    mkdirp "^0.5.1"
-    range-parser "^1.2.1"
-    webpack-log "^2.0.0"
-
-webpack-log@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
-  integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
-  dependencies:
-    ansi-colors "^3.0.0"
-    uuid "^3.3.2"
-
 webpack-sources@^1.4.0, webpack-sources@^1.4.1:
   version "1.4.3"
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
@@ -9609,7 +8802,7 @@ which-module@^2.0.0:
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -9685,15 +8878,6 @@ ws@^5.2.0:
   dependencies:
     async-limiter "~1.0.0"
 
-ws@~3.3.1:
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
-  integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
-  dependencies:
-    async-limiter "~1.0.0"
-    safe-buffer "~5.1.0"
-    ultron "~1.1.0"
-
 x-is-string@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
@@ -9704,11 +8888,6 @@ xml-name-validator@^3.0.0:
   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
 
-xmlhttprequest-ssl@~1.5.4:
-  version "1.5.5"
-  resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
-  integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
-
 xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -9724,11 +8903,6 @@ y18n@^3.2.1:
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
   integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
 
-yallist@^2.1.2:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
-  integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
 yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
@@ -9817,11 +8991,6 @@ yargs@^12.0.5:
     y18n "^3.2.1 || ^4.0.0"
     yargs-parser "^11.1.1"
 
-yeast@0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
-  integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
-
 zxcvbn@^4.4.2:
   version "4.4.2"
   resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"

From 802092bf9a6196324a9cc579735b6e6d2d74c704 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 11:53:18 +0000
Subject: [PATCH 20/86] All tests passing locally. We no longer need Chrome in
 buildkite

---
 .buildkite/pipeline.yaml          | 10 +---------
 test/stores/RoomViewStore-test.js | 15 ++++++++-------
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index be0d5e404c..8630271ce0 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -27,18 +27,12 @@ steps:
           image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
           propagate-environment: true
 
-  - label: ":karma: Tests"
+  - label: ":jest: Tests"
     agents:
       # We use a medium sized instance instead of the normal small ones because
       # webpack loves to gorge itself on resources.
       queue: "medium"
     command:
-      # Install chrome
-      - "echo '--- Installing Chrome'"
-      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
-      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
-      - "apt-get update"
-      - "apt-get install -y google-chrome-stable"
       # Run tests
       # TODO: Remove hacky chmod for BuildKite
       - "chmod +x ./scripts/ci/*.sh"
@@ -47,8 +41,6 @@ steps:
       - "./scripts/ci/install-deps.sh"
       - "echo '+++ Running Tests'"
       - "./scripts/ci/unit-tests.sh"
-    env:
-      CHROME_BIN: "/usr/bin/google-chrome-stable"
     plugins:
       - docker#v3.0.1:
           image: "node:10"
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index 83ec3d9c2e..f227ae69ab 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -27,13 +27,7 @@ describe('RoomViewStore', function() {
     });
 
     it('can be used to view a room by alias and join', function(done) {
-        peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"});
-        peg.get().joinRoom = async (roomAddress) => {
-            expect(roomAddress).toBe("#somealias2:aser.ver");
-            done();
-        };
-
-        RoomViewStore.addListener(() => {
+        const token = RoomViewStore.addListener(() => {
             // Wait until the room alias has resolved and the room ID is
             if (!RoomViewStore.isRoomLoading()) {
                 expect(RoomViewStore.getRoomId()).toBe("!randomcharacters:aser.ver");
@@ -42,6 +36,13 @@ describe('RoomViewStore', function() {
             }
         });
 
+        peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"});
+        peg.get().joinRoom = async (roomAddress) => {
+            token.remove(); // stop RVS listener
+            expect(roomAddress).toBe("#somealias2:aser.ver");
+            done();
+        };
+
         dispatch({ action: 'view_room', room_alias: '#somealias2:aser.ver' });
     });
 });

From c3415d21217c0e1e6ca802345b8428dc49b4cb34 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 12:09:01 +0000
Subject: [PATCH 21/86] delint

---
 test/components/views/elements/MemberEventListSummary-test.js | 1 -
 test/components/views/groups/GroupMemberList-test.js          | 1 -
 test/test-utils.js                                            | 2 --
 3 files changed, 4 deletions(-)

diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js
index a68c39eeeb..7b40916dda 100644
--- a/test/components/views/elements/MemberEventListSummary-test.js
+++ b/test/components/views/elements/MemberEventListSummary-test.js
@@ -2,7 +2,6 @@ import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ShallowRenderer from "react-test-renderer/shallow";
 import sdk from '../../../skinned-sdk';
-import * as languageHandler from '../../../../src/languageHandler';
 import * as testUtils from '../../../test-utils';
 
 // Give MELS a matrixClient in its child context
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index fd96c9f331..2b20ce0067 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -24,7 +24,6 @@ import sdk from "../../../skinned-sdk";
 import Matrix from "matrix-js-sdk";
 
 import * as TestUtils from "../../../test-utils";
-import * as languageHandler from "../../../../src/languageHandler";
 const { waitForUpdate } = TestUtils;
 
 const GroupMemberList = sdk.getComponent("views.groups.GroupMemberList");
diff --git a/test/test-utils.js b/test/test-utils.js
index 407791e9c3..13248c2851 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -22,8 +22,6 @@ export function getRenderer() {
  * TODO: once the components are updated to get their MatrixClients from
  * the react context, we can get rid of this and just inject a test client
  * via the context instead.
- *
- * @returns {sinon.Sandbox}; remember to call sandbox.restore afterwards.
  */
 export function stubClient() {
     const client = createTestClient();

From 386d6ec055c2229dd1642785a4aaad8f4522c20d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 12:16:40 +0000
Subject: [PATCH 22/86] we don't need to install riot-web for react-sdk unit
 tests

---
 .buildkite/pipeline.yaml |   2 +-
 karma.conf.js            | 228 ---------------------------------------
 scripts/ci/unit-tests.sh |  10 --
 3 files changed, 1 insertion(+), 239 deletions(-)
 delete mode 100644 karma.conf.js
 delete mode 100755 scripts/ci/unit-tests.sh

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index 8630271ce0..e3770f53c7 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -40,7 +40,7 @@ steps:
       - "echo '--- Installing Dependencies'"
       - "./scripts/ci/install-deps.sh"
       - "echo '+++ Running Tests'"
-      - "./scripts/ci/unit-tests.sh"
+      - "yarn test"
     plugins:
       - docker#v3.0.1:
           image: "node:10"
diff --git a/karma.conf.js b/karma.conf.js
deleted file mode 100644
index d55be049bb..0000000000
--- a/karma.conf.js
+++ /dev/null
@@ -1,228 +0,0 @@
-// karma.conf.js - the config file for karma, which runs our tests.
-
-var path = require('path');
-var fs = require('fs');
-
-/*
- * We use webpack to build our tests. It's a pain to have to wait for webpack
- * to build everything; however it's the easiest way to load our dependencies
- * from node_modules.
- *
- * If you run karma in multi-run mode (with `yarn test-multi`), it will watch
- * the tests for changes, and webpack will rebuild using a cache. This is much quicker
- * than a clean rebuild.
- */
-
-// the name of the test file. By default, a special file which runs all tests.
-//
-// TODO: this could be a pattern, and karma would run each file, with a
-// separate webpack bundle for each file. But then we get a separate instance
-// of the sdk, and each of the dependencies, for each test file, and everything
-// gets very confused. Can we persuade webpack to put all of the dependencies
-// in a 'common' bundle?
-//
-var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';
-
-
-process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
-
-function fileExists(name) {
-    try {
-        fs.statSync(name);
-        return true;
-    } catch (e) {
-        return false;
-    }
-}
-
-// try find the gemini-scrollbar css in an version-agnostic way
-var gsCss = 'node_modules/gemini-scrollbar/gemini-scrollbar.css';
-if (!fileExists(gsCss)) {
-    gsCss = 'node_modules/react-gemini-scrollbar/'+gsCss;
-}
-
-
-module.exports = function (config) {
-    config.set({
-        // frameworks to use
-        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
-        frameworks: ['mocha'],
-
-        // list of files / patterns to load in the browser
-        files: [
-            testFile,
-            gsCss,
-
-            // some images to reduce noise from the tests
-            {pattern: 'test/img/*', watched: false, included: false,
-             served: true, nocache: false},
-            // translation files
-            {pattern: 'src/i18n/strings/*', watcheed: false, included: false, served: true},
-            {pattern: 'test/i18n/*', watched: false, included: false, served: true},
-        ],
-
-        proxies: {
-            // redirect img links to the karma server
-            "/img/": "/base/test/img/",
-            // special languages.json file for the tests
-            "/i18n/languages.json": "/base/test/i18n/languages.json",
-            // and redirect i18n requests
-            "/i18n/": "/base/src/i18n/strings/",
-        },
-
-        // list of files to exclude
-        //
-        // This doesn't work. It turns out that it's webpack which does the
-        // watching of the /test directory (karma only watches `testFile`
-        // itself). Webpack watches the directory so that it can spot
-        // new tests, which is fair enough; unfortunately it triggers a rebuild
-        // every time a lockfile is created in that directory, and there
-        // doesn't seem to be any way to tell webpack to ignore particular
-        // files in a watched directory.
-        //
-        // exclude: [
-        //     '**/.#*'
-        // ],
-
-        // preprocess matching files before serving them to the browser
-        // available preprocessors:
-        // https://npmjs.org/browse/keyword/karma-preprocessor
-        preprocessors: {
-            'test/**/*.js': ['webpack', 'sourcemap']
-        },
-
-        // test results reporter to use
-        // possible values: 'dots', 'progress'
-        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
-        reporters: ['logcapture', 'spec', 'summary'],
-
-        specReporter: {
-            suppressErrorSummary: false, // do print error summary
-            suppressFailed: false, // do print information about failed tests
-            suppressPassed: false, // do print information about passed tests
-            showSpecTiming: true, // print the time elapsed for each spec
-        },
-
-        client: {
-            captureLogs: true,
-        },
-
-        // web server port
-        port: 9876,
-
-        // enable / disable colors in the output (reporters and logs)
-        colors: true,
-
-        // level of logging
-        // possible values: config.LOG_DISABLE || config.LOG_ERROR ||
-        // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
-        //
-        // This is strictly for logs that would be generated by the browser itself and we
-        // don't want to log about missing images, which are emitted on LOG_WARN.
-        logLevel: config.LOG_ERROR,
-
-        // enable / disable watching file and executing tests whenever any file
-        // changes
-        autoWatch: true,
-
-        // start these browsers
-        // available browser launchers:
-        // https://npmjs.org/browse/keyword/karma-launcher
-        browsers: [
-            'Chrome',
-            //'PhantomJS',
-            //'ChromeHeadless',
-        ],
-
-        customLaunchers: {
-            'VectorChromeHeadless': {
-                base: 'Chrome',
-                flags: [
-                    '--no-sandbox',
-                    // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
-                    '--headless',
-                    '--disable-gpu',
-                    // Without a remote debugging port, Google Chrome exits immediately.
-                    '--remote-debugging-port=9222',
-                ],
-            }
-        },
-
-        // Continuous Integration mode
-        // if true, Karma captures browsers, runs the tests and exits
-        // singleRun: false,
-
-        // Concurrency level
-        // how many browser should be started simultaneous
-        concurrency: Infinity,
-
-        webpack: {
-            module: {
-                rules: [
-                    {
-                        test: /\.js$/, loader: "babel-loader",
-                        include: [path.resolve('./src'),
-                                  path.resolve('./test'),
-                                 ]
-                    },
-                    {
-                        test: /\.(gif|png|svg|ttf|woff2)$/,
-                        loader: 'file-loader',
-                    },
-                ],
-                noParse: [
-                    // for cross platform compatibility use [\\\/] as the path separator
-                    // this ensures that the regex trips on both Windows and *nix
-
-                    // don't parse the languages within highlight.js. They
-                    // cause stack overflows
-                    // (https://github.com/webpack/webpack/issues/1721), and
-                    // there is no need for webpack to parse them - they can
-                    // just be included as-is.
-                    /highlight\.js[\\\/]lib[\\\/]languages/,
-
-                    // olm takes ages for webpack to process, and it's already heavily
-                    // optimised, so there is little to gain by us uglifying it.
-                    /olm[\\\/](javascript[\\\/])?olm\.js$/,
-
-                    // also disable parsing for sinon, because it
-                    // tries to do voodoo with 'require' which upsets
-                    // webpack (https://github.com/webpack/webpack/issues/304)
-                    /sinon[\\\/]pkg[\\\/]sinon\.js$/,
-                ],
-            },
-            resolve: {
-                alias: {
-                    // alias any requires to the react module to the one in our
-                    // path, otherwise we tend to get the react source included
-                    // twice when using `npm link` / `yarn link`.
-                    react: path.resolve('./node_modules/react'),
-
-                    'matrix-react-sdk': path.resolve('test/skinned-sdk.js'),
-                    'sinon': 'sinon/pkg/sinon.js',
-                },
-                modules: [
-                    path.resolve('./test'),
-                    "node_modules"
-                ],
-            },
-            devtool: 'inline-source-map',
-            externals: {
-                // Don't try to bundle electron: leave it as a commonjs dependency
-                // (the 'commonjs' here means it will output a 'require')
-                "electron": "commonjs electron",
-            },
-            // make sure we're flagged as development to avoid wasting time optimising
-            mode: 'development',
-        },
-
-        webpackMiddleware: {
-            stats: {
-                // don't fill the console up with a mahoosive list of modules
-                chunks: false,
-            },
-        },
-
-        browserNoActivityTimeout: 15000,
-    });
-};
diff --git a/scripts/ci/unit-tests.sh b/scripts/ci/unit-tests.sh
deleted file mode 100755
index 5b86190963..0000000000
--- a/scripts/ci/unit-tests.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-#
-# script which is run by the CI build (after `yarn test`).
-#
-# clones riot-web develop and runs the tests against our version of react-sdk.
-
-set -ev
-
-scripts/ci/build.sh
-yarn test

From f06a94388fbfa5f190c9b907e01c75ec20aef80b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 12:22:11 +0000
Subject: [PATCH 23/86] fix yarn test for bashy things

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 05129cb7c0..688839e3f8 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
     "stylelint": "stylelint 'res/css/**/*.scss'",
     "clean": "rimraf lib",
     "prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt",
-    "test": "jest --testMatch **/*-test.js",
+    "test": "jest --testMatch '**/*-test.js'",
     "e2etests": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
   },
   "dependencies": {

From bcba9a3e5081573c53fd135117749cafc68f0be3 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 12:23:51 +0000
Subject: [PATCH 24/86] fix yarn test for bashy things v2

---
 package.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 688839e3f8..a06c8dbcd3 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
     "stylelint": "stylelint 'res/css/**/*.scss'",
     "clean": "rimraf lib",
     "prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt",
-    "test": "jest --testMatch '**/*-test.js'",
+    "test": "jest",
     "e2etests": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
   },
   "dependencies": {
@@ -157,6 +157,7 @@
     "webpack-cli": "^3.1.1"
   },
   "jest": {
+    "testMatch": ["**/*-test.js"],
     "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
       "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"

From 409a111b02c548cfe1fa1ecee3104972bfb408cb Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 12:42:47 +0000
Subject: [PATCH 25/86] wait additional tick

---
 package.json                                 | 2 +-
 test/components/structures/GroupView-test.js | 2 +-
 test/utils/MegolmExportEncryption-test.js    | 1 -
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index a06c8dbcd3..aa2cba73fa 100644
--- a/package.json
+++ b/package.json
@@ -157,7 +157,7 @@
     "webpack-cli": "^3.1.1"
   },
   "jest": {
-    "testMatch": ["**/*-test.js"],
+    "testMatch": ["test/**/*-test.js"],
     "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
       "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"
diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index 31e7c26c9a..5f7e000aac 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -302,7 +302,7 @@ describe('GroupView', function() {
 
     it('should show a RoomDetailList after a successful /summary & /rooms (no rooms returned)', function() {
         const groupView = ReactTestUtils.findRenderedComponentWithType(root, GroupView);
-        const prom = waitForUpdate(groupView, 4).then(() => {
+        const prom = waitForUpdate(groupView, 5).then(() => {
             const roomDetailList = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_RoomDetailList');
             const roomDetailListElement = ReactDOM.findDOMNode(roomDetailList);
             expect(roomDetailListElement).toBeTruthy();
diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js
index b3a9782ce6..1fd305b0a6 100644
--- a/test/utils/MegolmExportEncryption-test.js
+++ b/test/utils/MegolmExportEncryption-test.js
@@ -74,7 +74,6 @@ describe('MegolmExportEncryption', function() {
     let MegolmExportEncryption;
 
     beforeAll(() => {
-        // window.crypto = { subtle: crypto.subtle, getRandomValues };
         window.crypto = { subtle: webCrypto.subtle, getRandomValues };
         MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
     });

From a2246374f12cb159f1e81d4a279d99f820b99711 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 13:05:18 +0000
Subject: [PATCH 26/86] correct testMatch so it doesn't try run js-sdk tests

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index aa2cba73fa..33fd5a3236 100644
--- a/package.json
+++ b/package.json
@@ -157,7 +157,7 @@
     "webpack-cli": "^3.1.1"
   },
   "jest": {
-    "testMatch": ["test/**/*-test.js"],
+    "testMatch": ["<rootDir>/test/**/*-test.js"],
     "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
       "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"

From b9e22f8141599d48a7155ef23eab053e1768c1f9 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 17 Dec 2019 13:11:30 +0000
Subject: [PATCH 27/86] add delay

---
 test/components/views/dialogs/InteractiveAuthDialog-test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/components/views/dialogs/InteractiveAuthDialog-test.js b/test/components/views/dialogs/InteractiveAuthDialog-test.js
index b047d6073b..610ad7c9f5 100644
--- a/test/components/views/dialogs/InteractiveAuthDialog-test.js
+++ b/test/components/views/dialogs/InteractiveAuthDialog-test.js
@@ -103,7 +103,7 @@ describe('InteractiveAuthDialog', function() {
             }));
             // let the request complete
             return sleep(1);
-        }).then(() => {
+        }).then(sleep(1)).then(() => {
             expect(onFinished).toBeCalledTimes(1);
             expect(onFinished).toBeCalledWith(true, {a: 1});
         });

From 4fe0150944f747e8ab2982dffa02bcbb1eb1368c Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 19 Dec 2019 10:51:55 +0000
Subject: [PATCH 28/86] Regen yarn.lock

---
 yarn.lock | 2328 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 1250 insertions(+), 1078 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index b8b877ab62..9cd4cad706 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,7 +2,7 @@
 # yarn lockfile v1
 
 
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35", "@babel/code-frame@^7.5.5":
   version "7.5.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
   integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
@@ -132,42 +132,6 @@
     lodash "^4.17.13"
     to-fast-properties "^2.0.0"
 
-"@jest/console@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0"
-  integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==
-  dependencies:
-    "@jest/source-map" "^24.9.0"
-    chalk "^2.0.1"
-    slash "^2.0.0"
-
-"@jest/source-map@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714"
-  integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==
-  dependencies:
-    callsites "^3.0.0"
-    graceful-fs "^4.1.15"
-    source-map "^0.6.0"
-
-"@jest/test-result@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca"
-  integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==
-  dependencies:
-    "@jest/console" "^24.9.0"
-    "@jest/types" "^24.9.0"
-    "@types/istanbul-lib-coverage" "^2.0.0"
-
-"@jest/types@^24.9.0":
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59"
-  integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==
-  dependencies:
-    "@types/istanbul-lib-coverage" "^2.0.0"
-    "@types/istanbul-reports" "^1.1.1"
-    "@types/yargs" "^13.0.0"
-
 "@mrmlnc/readdir-enhanced@^2.2.1":
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -181,41 +145,32 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
-"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0":
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393"
-  integrity sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==
+"@peculiar/asn1-schema@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-1.0.3.tgz#e55ff9e98a1cf31832629aabacf85be3edf13a48"
+  integrity sha512-Tfgj9eNJ6cTKEtEuidKenLHMx/Q5M8KEE9hnohHqvdpqHJXWYr5RlT3GjAHPjGXy5+mr7sSfuXfzE6aAkEGN7A==
   dependencies:
-    type-detect "4.0.8"
+    asn1js "^2.0.22"
+    tslib "^1.9.3"
 
-"@sinonjs/formatio@^2.0.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2"
-  integrity sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==
+"@peculiar/json-schema@^1.1.6":
+  version "1.1.9"
+  resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.9.tgz#b746e046b787607a1b2804f64437fda2527b3e62"
+  integrity sha512-F2ST2y/IQPgY+1QMw1Q33sqJbGDCeO3lGqI69SL3Hgo0++7iHqprUB1QyxB/A7bN3tuM65MBxoM2JLbwh42lsQ==
   dependencies:
-    samsam "1.3.0"
+    tslib "^1.10.0"
 
-"@sinonjs/formatio@^3.2.1":
-  version "3.2.2"
-  resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c"
-  integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==
+"@peculiar/webcrypto@^1.0.22":
+  version "1.0.22"
+  resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.0.22.tgz#9dae652fce6bacd9df15bc91965797cee33adf67"
+  integrity sha512-NP6H6ZGXUvJnQJCWzUgnRcQv+9nMCNwLUDhTwOxRUwPFvtHauMOl0oPTKUjbhInCMaE55gJqB4yc0YKbde6Exw==
   dependencies:
-    "@sinonjs/commons" "^1"
-    "@sinonjs/samsam" "^3.1.0"
-
-"@sinonjs/samsam@^3.1.0":
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a"
-  integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==
-  dependencies:
-    "@sinonjs/commons" "^1.3.0"
-    array-from "^2.1.1"
-    lodash "^4.17.15"
-
-"@sinonjs/text-encoding@^0.7.1":
-  version "0.7.1"
-  resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
-  integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
+    "@peculiar/asn1-schema" "^1.0.3"
+    "@peculiar/json-schema" "^1.1.6"
+    asn1js "^2.0.26"
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
+    webcrypto-core "^1.0.17"
 
 "@types/events@*":
   version "3.0.0"
@@ -231,26 +186,6 @@
     "@types/minimatch" "*"
     "@types/node" "*"
 
-"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
-  integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
-
-"@types/istanbul-lib-report@*":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
-  integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
-  dependencies:
-    "@types/istanbul-lib-coverage" "*"
-
-"@types/istanbul-reports@^1.1.1":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
-  integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
-  dependencies:
-    "@types/istanbul-lib-coverage" "*"
-    "@types/istanbul-lib-report" "*"
-
 "@types/json-schema@^7.0.3":
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
@@ -266,11 +201,6 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2"
   integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==
 
-"@types/stack-utils@^1.0.1":
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
-  integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
-
 "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@@ -292,18 +222,6 @@
     "@types/unist" "*"
     "@types/vfile-message" "*"
 
-"@types/yargs-parser@*":
-  version "13.1.0"
-  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228"
-  integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==
-
-"@types/yargs@^13.0.0":
-  version "13.0.3"
-  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380"
-  integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==
-  dependencies:
-    "@types/yargs-parser" "*"
-
 "@typescript-eslint/experimental-utils@^2.5.0":
   version "2.10.0"
   resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz#8db1656cdfd3d9dcbdbf360b8274dea76f0b2c2c"
@@ -482,34 +400,44 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
+abab@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
+  integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
+
 abbrev@1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
 
-accepts@~1.3.4:
-  version "1.3.7"
-  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
-  integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+acorn-globals@^4.1.0:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
+  integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
   dependencies:
-    mime-types "~2.1.24"
-    negotiator "0.6.2"
+    acorn "^6.0.1"
+    acorn-walk "^6.0.1"
 
 acorn-jsx@^5.0.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
   integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
 
-acorn@^6.0.7, acorn@^6.2.1:
+acorn-walk@^6.0.1:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
+  integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+
+acorn@^5.5.3:
+  version "5.7.3"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
+  integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
+
+acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.1:
   version "6.4.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
   integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==
 
-after@0.8.2:
-  version "0.8.2"
-  resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
-  integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-
 agent-base@4, agent-base@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@@ -556,12 +484,7 @@ another-json@^0.2.0:
   resolved "https://registry.yarnpkg.com/another-json/-/another-json-0.2.0.tgz#b5f4019c973b6dd5c6506a2d93469cb6d32aeedc"
   integrity sha1-tfQBnJc7bdXGUGotk0acttMq7tw=
 
-ansi-colors@^3.0.0:
-  version "3.2.4"
-  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
-  integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-
-ansi-escapes@^3.2.0:
+ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
   integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
@@ -576,7 +499,7 @@ ansi-regex@^3.0.0:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
   integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
 
-ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+ansi-regex@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
   integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
@@ -609,13 +532,12 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-anymatch@~3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
-  integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
+append-transform@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+  integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
   dependencies:
-    normalize-path "^3.0.0"
-    picomatch "^2.0.4"
+    default-require-extensions "^1.0.0"
 
 aproba@^1.0.3, aproba@^1.1.1:
   version "1.2.0"
@@ -659,16 +581,16 @@ arr-union@^3.1.0:
   resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
 
+array-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+  integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
+
 array-find-index@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
   integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
 
-array-from@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195"
-  integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=
-
 array-includes@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
@@ -699,11 +621,6 @@ array-unique@^0.3.2:
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
   integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
 
-arraybuffer.slice@~0.0.7:
-  version "0.0.7"
-  resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
-  integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
-
 arrify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -730,6 +647,13 @@ asn1@~0.2.3:
   dependencies:
     safer-buffer "~2.1.0"
 
+asn1js@^2.0.22, asn1js@^2.0.26:
+  version "2.0.26"
+  resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-2.0.26.tgz#0a6d435000f556a96c6012969d9704d981b71251"
+  integrity sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==
+  dependencies:
+    pvutils latest
+
 assert-plus@1.0.0, assert-plus@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
@@ -763,7 +687,7 @@ async-limiter@~1.0.0:
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
   integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
 
-async@^2.5.0, async@^2.6.2:
+async@^2.1.4, async@^2.5.0:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
   integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
@@ -834,7 +758,7 @@ babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
-babel-core@^6.26.0, babel-core@^6.26.3:
+babel-core@^6.0.0, babel-core@^6.26.0, babel-core@^6.26.3:
   version "6.26.3"
   resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
   integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
@@ -871,7 +795,7 @@ babel-eslint@^10.0.1:
     eslint-visitor-keys "^1.0.0"
     resolve "^1.12.0"
 
-babel-generator@^6.26.0:
+babel-generator@^6.18.0, babel-generator@^6.26.0:
   version "6.26.1"
   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
   integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
@@ -1007,6 +931,14 @@ babel-helpers@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
+babel-jest@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
+  integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
+  dependencies:
+    babel-plugin-istanbul "^4.1.6"
+    babel-preset-jest "^23.2.0"
+
 babel-loader@^7.1.5:
   version "7.1.5"
   resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
@@ -1035,6 +967,21 @@ babel-plugin-check-es2015-constants@^6.22.0:
   dependencies:
     babel-runtime "^6.22.0"
 
+babel-plugin-istanbul@^4.1.6:
+  version "4.1.6"
+  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
+  integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
+  dependencies:
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+    find-up "^2.1.0"
+    istanbul-lib-instrument "^1.10.1"
+    test-exclude "^4.2.1"
+
+babel-plugin-jest-hoist@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
+  integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
+
 babel-plugin-syntax-async-functions@^6.8.0:
   version "6.13.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@@ -1065,7 +1012,7 @@ babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
   integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
 
-babel-plugin-syntax-object-rest-spread@^6.8.0:
+babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0:
   version "6.13.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
   integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
@@ -1432,6 +1379,14 @@ babel-preset-flow@^6.23.0:
   dependencies:
     babel-plugin-transform-flow-strip-types "^6.22.0"
 
+babel-preset-jest@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
+  integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
+  dependencies:
+    babel-plugin-jest-hoist "^23.2.0"
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+
 babel-preset-react@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
@@ -1465,7 +1420,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtim
     core-js "^2.4.0"
     regenerator-runtime "^0.11.0"
 
-babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
   integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
@@ -1476,7 +1431,7 @@ babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
     babylon "^6.18.0"
     lodash "^4.17.4"
 
-babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
   integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
@@ -1491,7 +1446,7 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0:
     invariant "^2.2.2"
     lodash "^4.17.4"
 
-babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
   integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
@@ -1506,11 +1461,6 @@ babylon@^6.18.0:
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
   integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
 
-backo2@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
-  integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
-
 bail@^1.0.0:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.4.tgz#7181b66d508aa3055d3f6c13f0a0c720641dde9b"
@@ -1528,21 +1478,11 @@ base-x@^3.0.2:
   dependencies:
     safe-buffer "^5.0.1"
 
-base64-arraybuffer@0.1.5:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
-  integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
-
 base64-js@^1.0.2:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
   integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
 
-base64id@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
-  integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=
-
 base@^0.11.1:
   version "0.11.2"
   resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@@ -1563,13 +1503,6 @@ bcrypt-pbkdf@^1.0.0:
   dependencies:
     tweetnacl "^0.14.3"
 
-better-assert@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
-  integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=
-  dependencies:
-    callsite "1.0.0"
-
 big.js@^5.2.2:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -1580,17 +1513,19 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
-binary-extensions@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
-  integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
+bindings@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
+  integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
+  dependencies:
+    file-uri-to-path "1.0.0"
 
-blob@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
-  integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
+bluebird@^2.9.27:
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
+  integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
 
-bluebird@^3.3.0, bluebird@^3.5.0, bluebird@^3.5.5:
+bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
@@ -1605,22 +1540,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
   integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
 
-body-parser@^1.16.1:
-  version "1.19.0"
-  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
-  integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
-  dependencies:
-    bytes "3.1.0"
-    content-type "~1.0.4"
-    debug "2.6.9"
-    depd "~1.1.2"
-    http-errors "1.7.2"
-    iconv-lite "0.4.24"
-    on-finished "~2.3.0"
-    qs "6.7.0"
-    raw-body "2.4.0"
-    type-is "~1.6.17"
-
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -1654,13 +1573,6 @@ braces@^2.3.1, braces@^2.3.2:
     split-string "^3.0.2"
     to-regex "^3.0.1"
 
-braces@^3.0.2, braces@~3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
-  integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
-  dependencies:
-    fill-range "^7.0.1"
-
 brorand@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@@ -1671,15 +1583,22 @@ browser-encrypt-attachment@^0.3.0:
   resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c"
   integrity sha1-IFqUyq3w3H6BQTlBgS9lW9GQ/xw=
 
+browser-process-hrtime@^0.1.2:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
+  integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==
+
 browser-request@^0.3.3:
   version "0.3.3"
   resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17"
   integrity sha1-ns5bWsqJopkyJC4Yv5M975h2zBc=
 
-browser-stdout@1.3.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
-  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
+browser-resolve@^1.11.3:
+  version "1.11.3"
+  resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
+  integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
+  dependencies:
+    resolve "1.1.7"
 
 browserify-aes@^1.0.0, browserify-aes@^1.0.4:
   version "1.2.0"
@@ -1756,23 +1675,12 @@ bs58@^4.0.1:
   dependencies:
     base-x "^3.0.2"
 
-buffer-alloc-unsafe@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
-  integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-
-buffer-alloc@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
-  integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
+bser@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+  integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
   dependencies:
-    buffer-alloc-unsafe "^1.1.0"
-    buffer-fill "^1.0.0"
-
-buffer-fill@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
-  integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
+    node-int64 "^0.4.0"
 
 buffer-from@^1.0.0:
   version "1.1.1"
@@ -1798,11 +1706,6 @@ builtin-status-codes@^3.0.0:
   resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
   integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
 
-bytes@3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
-  integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
 cacache@^12.0.0, cacache@^12.0.2:
   version "12.0.3"
   resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
@@ -1858,11 +1761,6 @@ caller-path@^2.0.0:
   dependencies:
     caller-callsite "^2.0.0"
 
-callsite@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
-  integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
-
 callsites@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
@@ -1897,6 +1795,13 @@ caniuse-lite@^1.0.30001012:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0"
   integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==
 
+capture-exit@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
+  integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
+  dependencies:
+    rsvp "^3.3.3"
+
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1912,7 +1817,7 @@ chain-function@^1.0.0:
   resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc"
   integrity sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==
 
-chalk@2.4.2, "chalk@^1.1.3 || 2.x", chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -1992,21 +1897,6 @@ chokidar@^2.0.2, chokidar@^2.1.2:
   optionalDependencies:
     fsevents "^1.2.7"
 
-chokidar@^3.0.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6"
-  integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==
-  dependencies:
-    anymatch "~3.1.1"
-    braces "~3.0.2"
-    glob-parent "~5.1.0"
-    is-binary-path "~2.1.0"
-    is-glob "~4.0.1"
-    normalize-path "~3.0.0"
-    readdirp "~3.2.0"
-  optionalDependencies:
-    fsevents "~2.1.1"
-
 chownr@^1.1.1:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
@@ -2019,6 +1909,11 @@ chrome-trace-event@^1.0.2:
   dependencies:
     tslib "^1.9.0"
 
+ci-info@^1.5.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
 cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -2072,15 +1967,6 @@ cliui@^5.0.0:
     strip-ansi "^5.2.0"
     wrap-ansi "^5.1.0"
 
-clone-deep@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
-  integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
-  dependencies:
-    is-plain-object "^2.0.4"
-    kind-of "^6.0.2"
-    shallow-clone "^3.0.0"
-
 clone-regexp@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f"
@@ -2089,6 +1975,11 @@ clone-regexp@^1.0.0:
     is-regexp "^1.0.0"
     is-supported-regexp-flag "^1.0.0"
 
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+  integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
+
 code-point-at@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
@@ -2119,11 +2010,6 @@ color-name@1.1.3:
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
   integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
 
-colors@^1.1.0, colors@^1.1.2:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
-  integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-
 combined-stream@^1.0.6, combined-stream@~1.0.6:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -2131,12 +2017,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
   dependencies:
     delayed-stream "~1.0.0"
 
-commander@2.15.1:
-  version "2.15.1"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
-  integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
-
-commander@^2.11.0, commander@^2.20.0:
+commander@^2.11.0, commander@^2.20.0, commander@~2.20.3:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -2156,26 +2037,11 @@ commonmark@^0.28.1:
     minimist "~ 1.2.0"
     string.prototype.repeat "^0.2.0"
 
-component-bind@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
-  integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=
-
-component-emitter@1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
-  integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
-
 component-emitter@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
   integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
 
-component-inherit@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-  integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
-
 concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2206,16 +2072,6 @@ concurrently@^4.0.1:
     tree-kill "^1.2.1"
     yargs "^12.0.5"
 
-connect@^3.6.0:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
-  integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
-  dependencies:
-    debug "2.6.9"
-    finalhandler "1.1.2"
-    parseurl "~1.3.3"
-    utils-merge "1.0.1"
-
 console-browserify@^1.1.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
@@ -2231,23 +2087,18 @@ constants-browserify@^1.0.0:
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
   integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
 
-content-type@^1.0.2, content-type@~1.0.4:
+content-type@^1.0.2:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
-convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
+convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
   integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
   dependencies:
     safe-buffer "~5.1.1"
 
-cookie@0.3.1:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
-  integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
-
 copy-concurrently@^1.0.0:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
@@ -2379,6 +2230,18 @@ cssesc@^3.0.0:
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
   integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
 
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+  version "0.3.8"
+  resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+  integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
+  integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
+  dependencies:
+    cssom "0.3.x"
+
 currently-unhandled@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -2386,11 +2249,6 @@ currently-unhandled@^0.4.1:
   dependencies:
     array-find-index "^1.0.1"
 
-custom-event@~1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
-  integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
-
 cyclist@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@@ -2403,36 +2261,40 @@ dashdash@^1.12.0:
   dependencies:
     assert-plus "^1.0.0"
 
+data-urls@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
+  integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
+  dependencies:
+    abab "^2.0.0"
+    whatwg-mimetype "^2.2.0"
+    whatwg-url "^7.0.0"
+
 date-fns@^1.30.1:
   version "1.30.1"
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
   integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
 
-date-format@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
-  integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==
-
 date-names@^0.1.11:
   version "0.1.13"
   resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.13.tgz#c4358f6f77c8056e2f5ea68fdbb05f0bf1e53bd0"
   integrity sha512-IxxoeD9tdx8pXVcmqaRlPvrXIsSrSrIZzfzlOkm9u+hyzKp5Wk/odt9O/gd7Ockzy8n/WHeEpTVJ2bF3mMV4LA==
 
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
-  version "2.6.9"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
-  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
-  dependencies:
-    ms "2.0.0"
-
-debug@3.1.0, debug@~3.1.0:
+debug@3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
   integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
   dependencies:
     ms "2.0.0"
 
-debug@^3.0.0, debug@^3.1.0, debug@^3.2.6:
+debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.1.0, debug@^3.2.6:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
   integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -2454,7 +2316,7 @@ decamelize-keys@^1.0.0:
     decamelize "^1.1.0"
     map-obj "^1.0.0"
 
-decamelize@^1.1.0, decamelize@^1.2.0:
+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -2474,6 +2336,13 @@ deep-is@~0.1.3:
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 
+default-require-extensions@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+  integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
+  dependencies:
+    strip-bom "^2.0.0"
+
 define-properties@^1.1.2, define-properties@^1.1.3, define-properties@~1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2513,11 +2382,6 @@ delegates@^1.0.0:
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
   integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
 
-depd@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
-  integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
 des.js@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
@@ -2543,16 +2407,16 @@ detect-libc@^1.0.2:
   resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
   integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
 
+detect-newline@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+  integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
+
 detect-node@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
   integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
 
-di@^0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
-  integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
-
 diff-dom@^4.1.3:
   version "4.1.6"
   resolved "https://registry.yarnpkg.com/diff-dom/-/diff-dom-4.1.6.tgz#ecd20f4b34703d777b7956790fc7e28e5ff3fece"
@@ -2566,12 +2430,7 @@ diff-match-patch@^1.0.4:
   resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
   integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
 
-diff-sequences@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
-  integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
-
-diff@3.5.0, diff@^3.5.0:
+diff@^3.2.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
@@ -2618,16 +2477,6 @@ dom-helpers@^3.2.0:
   dependencies:
     "@babel/runtime" "^7.1.2"
 
-dom-serialize@^2.2.0:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
-  integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=
-  dependencies:
-    custom-event "~1.0.0"
-    ent "~2.2.0"
-    extend "^3.0.0"
-    void-elements "^2.0.0"
-
 dom-serializer@0:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@@ -2651,6 +2500,13 @@ domelementtype@^2.0.1:
   resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
   integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
 
+domexception@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
+  integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
+  dependencies:
+    webidl-conversions "^4.0.2"
+
 domhandler@^2.3.0:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
@@ -2683,6 +2539,13 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
+ecc-jsbn@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.0.1.tgz#970577ba31b4976fb1889a298cb7451d896c466d"
+  integrity sha1-lwV3ujG0l2+xiJopjLdFHYlsRm0=
+  dependencies:
+    jsbn "git+https://github.com/rynomad/jsbn.git"
+
 ecc-jsbn@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@@ -2691,10 +2554,11 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
-ee-first@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
-  integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+"ecc-qj@git+https://github.com/rynomad/ecc.git":
+  version "0.0.1"
+  resolved "git+https://github.com/rynomad/ecc.git#a8c599363dab87a5c95274338d863233f00f7c4a"
+  dependencies:
+    nan "^1.6.2"
 
 electron-to-chromium@^1.3.317:
   version "1.3.322"
@@ -2739,11 +2603,6 @@ emojis-list@^2.0.0:
   resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
   integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
 
-encodeurl@~1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
-  integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-
 encoding@^0.1.11:
   version "0.1.12"
   resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
@@ -2758,46 +2617,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
-engine.io-client@~3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36"
-  integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==
-  dependencies:
-    component-emitter "1.2.1"
-    component-inherit "0.0.3"
-    debug "~3.1.0"
-    engine.io-parser "~2.1.1"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    ws "~3.3.1"
-    xmlhttprequest-ssl "~1.5.4"
-    yeast "0.1.2"
-
-engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6"
-  integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==
-  dependencies:
-    after "0.8.2"
-    arraybuffer.slice "~0.0.7"
-    base64-arraybuffer "0.1.5"
-    blob "0.0.5"
-    has-binary2 "~1.0.2"
-
-engine.io@~3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2"
-  integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==
-  dependencies:
-    accepts "~1.3.4"
-    base64id "1.0.0"
-    cookie "0.3.1"
-    debug "~3.1.0"
-    engine.io-parser "~2.1.0"
-    ws "~3.3.1"
-
 enhanced-resolve@4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
@@ -2816,11 +2635,6 @@ enhanced-resolve@^4.1.0:
     memory-fs "^0.5.0"
     tapable "^1.0.0"
 
-ent@~2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
-  integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
 entities@^1.1.1, "entities@~ 1.1.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@@ -2843,7 +2657,7 @@ errno@^0.1.3, errno@~0.1.7:
   dependencies:
     prr "~1.0.1"
 
-error-ex@^1.3.1:
+error-ex@^1.2.0, error-ex@^1.3.1:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
   integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
@@ -2866,6 +2680,23 @@ es-abstract@^1.12.0, es-abstract@^1.15.0, es-abstract@^1.16.2, es-abstract@^1.7.
     string.prototype.trimleft "^2.1.0"
     string.prototype.trimright "^2.1.0"
 
+es-abstract@^1.17.0-next.1:
+  version "1.17.0-next.1"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172"
+  integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==
+  dependencies:
+    es-to-primitive "^1.2.1"
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-symbols "^1.0.1"
+    is-callable "^1.1.4"
+    is-regex "^1.0.4"
+    object-inspect "^1.7.0"
+    object-keys "^1.1.1"
+    object.assign "^4.1.0"
+    string.prototype.trimleft "^2.1.0"
+    string.prototype.trimright "^2.1.0"
+
 es-get-iterator@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.0.1.tgz#ebc4d3bbc2d59dd95a0ecef441ca2dbce7d9e2cd"
@@ -2900,16 +2731,28 @@ es6-promisify@^5.0.0:
   dependencies:
     es6-promise "^4.0.3"
 
-escape-html@^1.0.3, escape-html@~1.0.3:
+escape-html@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
 
+escodegen@^1.9.1:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
+  integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==
+  dependencies:
+    esprima "^3.1.3"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    optionator "^0.8.1"
+  optionalDependencies:
+    source-map "~0.6.1"
+
 eslint-config-google@^0.7.1:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.7.1.tgz#5598f8498e9e078420f34b80495b8d959f651fb2"
@@ -3046,6 +2889,11 @@ espree@^5.0.1:
     acorn-jsx "^5.0.0"
     eslint-visitor-keys "^1.0.0"
 
+esprima@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+  integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
+
 esprima@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@@ -3070,7 +2918,7 @@ esrever@^0.2.0:
   resolved "https://registry.yarnpkg.com/esrever/-/esrever-0.2.0.tgz#96e9d28f4f1b1a76784cd5d490eaae010e7407b8"
   integrity sha1-lunSj08bGnZ4TNXUkOquAQ50B7g=
 
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
   integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
@@ -3090,11 +2938,6 @@ esutils@^2.0.2:
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
   integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
 
-eventemitter3@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
-  integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
-
 events@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@@ -3115,6 +2958,13 @@ except@^0.1.3:
   dependencies:
     indexof "0.0.1"
 
+exec-sh@^0.2.0:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
+  integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
+  dependencies:
+    merge "^1.2.0"
+
 execa@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
@@ -3135,6 +2985,11 @@ execall@^1.0.0:
   dependencies:
     clone-regexp "^1.0.0"
 
+exit@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+  integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+
 expand-brackets@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -3182,17 +3037,17 @@ expect@^1.20.2:
     object-keys "^1.0.9"
     tmatch "^2.0.1"
 
-expect@^24.1.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca"
-  integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==
+expect@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
+  integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
   dependencies:
-    "@jest/types" "^24.9.0"
     ansi-styles "^3.2.0"
-    jest-get-type "^24.9.0"
-    jest-matcher-utils "^24.9.0"
-    jest-message-util "^24.9.0"
-    jest-regex-util "^24.9.0"
+    jest-diff "^23.6.0"
+    jest-get-type "^22.1.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
 
 extend-shallow@^2.0.1:
   version "2.0.1"
@@ -3281,6 +3136,13 @@ fast-levenshtein@~2.0.6:
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 
+fb-watchman@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
+  integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==
+  dependencies:
+    bser "2.1.1"
+
 fbemitter@^2.0.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865"
@@ -3349,11 +3211,24 @@ file-saver@^1.3.3:
   resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8"
   integrity sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg==
 
+file-uri-to-path@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
+  integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
+
 filename-regex@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
   integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
 
+fileset@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
+  dependencies:
+    glob "^7.0.3"
+    minimatch "^3.0.3"
+
 filesize@3.5.6:
   version "3.5.6"
   resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a"
@@ -3380,26 +3255,6 @@ fill-range@^4.0.0:
     repeat-string "^1.6.1"
     to-regex-range "^2.1.0"
 
-fill-range@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
-  integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
-  dependencies:
-    to-regex-range "^5.0.1"
-
-finalhandler@1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
-  integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
-  dependencies:
-    debug "2.6.9"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    on-finished "~2.3.0"
-    parseurl "~1.3.3"
-    statuses "~1.5.0"
-    unpipe "~1.0.0"
-
 find-cache-dir@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
@@ -3426,6 +3281,14 @@ find-up@4.1.0:
     locate-path "^5.0.0"
     path-exists "^4.0.0"
 
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
 find-up@^2.0.0, find-up@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
@@ -3496,13 +3359,6 @@ focus-visible@^5.0.2:
   resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.0.2.tgz#4fae9cf40458b73c10701c9774c462e3ccd53caf"
   integrity sha512-zT2fj/bmOgEBjqGbURGlowTmCwsIs3bRDMr/sFZz8Ly7VkEiwuCn9swNTL3pPuf8Oua2de7CLuKdnuNajWdDsQ==
 
-follow-redirects@^1.0.0:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f"
-  integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==
-  dependencies:
-    debug "^3.0.0"
-
 for-in@^1.0.1, for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -3549,22 +3405,6 @@ from2@^2.1.0:
     inherits "^2.0.1"
     readable-stream "^2.0.0"
 
-fs-access@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
-  integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=
-  dependencies:
-    null-check "^1.0.0"
-
-fs-extra@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
-  integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
-  dependencies:
-    graceful-fs "^4.1.2"
-    jsonfile "^4.0.0"
-    universalify "^0.1.0"
-
 fs-minipass@^1.2.5:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
@@ -3600,10 +3440,13 @@ fsevents@^1.0.0, fsevents@^1.2.7:
     nan "^2.12.1"
     node-pre-gyp "^0.12.0"
 
-fsevents@~2.1.1:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
-  integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
+fsevents@^1.2.3:
+  version "1.2.11"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3"
+  integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==
+  dependencies:
+    bindings "^1.5.0"
+    nan "^2.12.1"
 
 function-bind@^1.1.1:
   version "1.1.1"
@@ -3717,13 +3560,6 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
 
-glob-parent@~5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
-  integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==
-  dependencies:
-    is-glob "^4.0.1"
-
 glob-to-regexp@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
@@ -3734,18 +3570,6 @@ glob-to-regexp@^0.4.1:
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
   integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
 
-glob@7.1.2:
-  version "7.1.2"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
-  integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.4"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
 glob@^5.0.14:
   version "5.0.15"
   resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
@@ -3757,7 +3581,7 @@ glob@^5.0.14:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.1.6"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
   integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -3841,15 +3665,26 @@ gonzales-pe@^4.2.3:
   dependencies:
     minimist "1.1.x"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
   integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
 
-growl@1.10.5:
-  version "1.10.5"
-  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
-  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
+growly@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+  integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
+
+handlebars@^4.0.3:
+  version "4.5.3"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
+  integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
+  dependencies:
+    neo-async "^2.6.0"
+    optimist "^0.6.1"
+    source-map "^0.6.1"
+  optionalDependencies:
+    uglify-js "^3.1.4"
 
 har-schema@^2.0.0:
   version "2.0.0"
@@ -3871,17 +3706,10 @@ has-ansi@^2.0.0:
   dependencies:
     ansi-regex "^2.0.0"
 
-has-binary2@~1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
-  integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==
-  dependencies:
-    isarray "2.0.1"
-
-has-cors@1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
-  integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
 
 has-flag@^2.0.0:
   version "2.0.0"
@@ -3957,11 +3785,6 @@ hash.js@^1.0.0, hash.js@^1.0.3:
     inherits "^2.0.3"
     minimalistic-assert "^1.0.1"
 
-he@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
-  integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
-
 highlight.js@^9.15.8:
   version "9.16.2"
   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e"
@@ -4010,6 +3833,13 @@ hosted-git-info@^2.1.4:
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
   integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
 
+html-encoding-sniffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
+  integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
+  dependencies:
+    whatwg-encoding "^1.0.1"
+
 html-tags@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
@@ -4032,17 +3862,6 @@ http-cache-semantics@^3.8.1:
   resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
   integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
 
-http-errors@1.7.2:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
-  integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
-  dependencies:
-    depd "~1.1.2"
-    inherits "2.0.3"
-    setprototypeof "1.1.1"
-    statuses ">= 1.5.0 < 2"
-    toidentifier "1.0.0"
-
 http-proxy-agent@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@@ -4051,15 +3870,6 @@ http-proxy-agent@^2.1.0:
     agent-base "4"
     debug "3.1.0"
 
-http-proxy@^1.13.0:
-  version "1.18.0"
-  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
-  integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
-  dependencies:
-    eventemitter3 "^4.0.0"
-    follow-redirects "^1.0.0"
-    requires-port "^1.0.0"
-
 http-signature@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@@ -4157,6 +3967,14 @@ import-local@2.0.0:
     pkg-dir "^3.0.0"
     resolve-cwd "^2.0.0"
 
+import-local@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+  integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
+  dependencies:
+    pkg-dir "^2.0.0"
+    resolve-cwd "^2.0.0"
+
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -4317,13 +4135,6 @@ is-binary-path@^1.0.0:
   dependencies:
     binary-extensions "^1.0.0"
 
-is-binary-path@~2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
-  integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
-  dependencies:
-    binary-extensions "^2.0.0"
-
 is-boolean-object@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93"
@@ -4344,6 +4155,13 @@ is-callable@^1.0.4, is-callable@^1.1.4:
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
   integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
 
+is-ci@^1.0.10:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+  integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+  dependencies:
+    ci-info "^1.5.0"
+
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -4473,6 +4291,11 @@ is-fullwidth-code-point@^3.0.0:
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
   integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
 
+is-generator-fn@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
+  integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
+
 is-generator-function@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
@@ -4492,7 +4315,7 @@ is-glob@^3.1.0:
   dependencies:
     is-extglob "^2.1.0"
 
-is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
+is-glob@^4.0.0, is-glob@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
   integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@@ -4550,11 +4373,6 @@ is-number@^4.0.0:
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
   integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
 
-is-number@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
-  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
 is-obj@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@@ -4631,6 +4449,11 @@ is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+
 is-weakmap@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.0.tgz#88bd0b8ec3a5724477637d58ed96cb00552593fd"
@@ -4666,33 +4489,16 @@ is-wsl@^1.1.0:
   resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
   integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
 
-isarray@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
-  integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
 isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
 
-isarray@2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
-  integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
-
 isarray@^2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
   integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
 
-isbinaryfile@^3.0.0:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80"
-  integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==
-  dependencies:
-    buffer-alloc "^1.2.0"
-
 isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -4728,43 +4534,249 @@ isstream@~0.1.2:
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
-jest-diff@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
-  integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
+istanbul-api@^1.3.1:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
+  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
+  dependencies:
+    async "^2.1.4"
+    fileset "^2.0.2"
+    istanbul-lib-coverage "^1.2.1"
+    istanbul-lib-hook "^1.2.2"
+    istanbul-lib-instrument "^1.10.2"
+    istanbul-lib-report "^1.1.5"
+    istanbul-lib-source-maps "^1.2.6"
+    istanbul-reports "^1.5.1"
+    js-yaml "^3.7.0"
+    mkdirp "^0.5.1"
+    once "^1.4.0"
+
+istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
+  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
+
+istanbul-lib-hook@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
+  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+  dependencies:
+    append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
+  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+  dependencies:
+    babel-generator "^6.18.0"
+    babel-template "^6.16.0"
+    babel-traverse "^6.18.0"
+    babel-types "^6.18.0"
+    babylon "^6.18.0"
+    istanbul-lib-coverage "^1.2.1"
+    semver "^5.3.0"
+
+istanbul-lib-report@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
+  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+  dependencies:
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    path-parse "^1.0.5"
+    supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
+  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+  dependencies:
+    debug "^3.1.0"
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    rimraf "^2.6.1"
+    source-map "^0.5.3"
+
+istanbul-reports@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
+  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
+  dependencies:
+    handlebars "^4.0.3"
+
+jest-changed-files@^23.4.2:
+  version "23.4.2"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
+  integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+  dependencies:
+    throat "^4.0.0"
+
+jest-cli@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
+  integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    glob "^7.1.2"
+    graceful-fs "^4.1.11"
+    import-local "^1.0.0"
+    is-ci "^1.0.10"
+    istanbul-api "^1.3.1"
+    istanbul-lib-coverage "^1.2.0"
+    istanbul-lib-instrument "^1.10.1"
+    istanbul-lib-source-maps "^1.2.4"
+    jest-changed-files "^23.4.2"
+    jest-config "^23.6.0"
+    jest-environment-jsdom "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve-dependencies "^23.6.0"
+    jest-runner "^23.6.0"
+    jest-runtime "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    jest-watcher "^23.4.0"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    node-notifier "^5.2.1"
+    prompts "^0.1.9"
+    realpath-native "^1.0.0"
+    rimraf "^2.5.4"
+    slash "^1.0.0"
+    string-length "^2.0.0"
+    strip-ansi "^4.0.0"
+    which "^1.2.12"
+    yargs "^11.0.0"
+
+jest-config@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
+  integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-jest "^23.6.0"
+    chalk "^2.0.1"
+    glob "^7.1.1"
+    jest-environment-jsdom "^23.4.0"
+    jest-environment-node "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-jasmine2 "^23.6.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    pretty-format "^23.6.0"
+
+jest-diff@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
+  integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
   dependencies:
     chalk "^2.0.1"
-    diff-sequences "^24.9.0"
-    jest-get-type "^24.9.0"
-    pretty-format "^24.9.0"
+    diff "^3.2.0"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
 
-jest-get-type@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
-  integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
+jest-docblock@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
+  integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
+  dependencies:
+    detect-newline "^2.1.0"
 
-jest-matcher-utils@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073"
-  integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==
+jest-each@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
+  integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
   dependencies:
     chalk "^2.0.1"
-    jest-diff "^24.9.0"
-    jest-get-type "^24.9.0"
-    pretty-format "^24.9.0"
+    pretty-format "^23.6.0"
 
-jest-message-util@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3"
-  integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==
+jest-environment-jsdom@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
+  integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
   dependencies:
-    "@babel/code-frame" "^7.0.0"
-    "@jest/test-result" "^24.9.0"
-    "@jest/types" "^24.9.0"
-    "@types/stack-utils" "^1.0.1"
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+    jsdom "^11.5.1"
+
+jest-environment-node@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
+  integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
+  dependencies:
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+
+jest-get-type@^22.1.0:
+  version "22.4.3"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
+  integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+
+jest-haste-map@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
+  integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+  dependencies:
+    fb-watchman "^2.0.0"
+    graceful-fs "^4.1.11"
+    invariant "^2.2.4"
+    jest-docblock "^23.2.0"
+    jest-serializer "^23.0.1"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    sane "^2.0.0"
+
+jest-jasmine2@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
+  integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
+  dependencies:
+    babel-traverse "^6.0.0"
     chalk "^2.0.1"
-    micromatch "^3.1.10"
-    slash "^2.0.0"
+    co "^4.6.0"
+    expect "^23.6.0"
+    is-generator-fn "^1.0.0"
+    jest-diff "^23.6.0"
+    jest-each "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    pretty-format "^23.6.0"
+
+jest-leak-detector@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
+  integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+  dependencies:
+    pretty-format "^23.6.0"
+
+jest-matcher-utils@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
+  integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
+
+jest-message-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
+  integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
+  dependencies:
+    "@babel/code-frame" "^7.0.0-beta.35"
+    chalk "^2.0.1"
+    micromatch "^2.3.11"
+    slash "^1.0.0"
     stack-utils "^1.0.1"
 
 jest-mock@^23.2.0:
@@ -4772,10 +4784,134 @@ jest-mock@^23.2.0:
   resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
   integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
 
-jest-regex-util@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636"
-  integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==
+jest-regex-util@^23.3.0:
+  version "23.3.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
+  integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
+
+jest-resolve-dependencies@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
+  integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+  dependencies:
+    jest-regex-util "^23.3.0"
+    jest-snapshot "^23.6.0"
+
+jest-resolve@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
+  integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+  dependencies:
+    browser-resolve "^1.11.3"
+    chalk "^2.0.1"
+    realpath-native "^1.0.0"
+
+jest-runner@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
+  integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+  dependencies:
+    exit "^0.1.2"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-docblock "^23.2.0"
+    jest-haste-map "^23.6.0"
+    jest-jasmine2 "^23.6.0"
+    jest-leak-detector "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-runtime "^23.6.0"
+    jest-util "^23.4.0"
+    jest-worker "^23.2.0"
+    source-map-support "^0.5.6"
+    throat "^4.0.0"
+
+jest-runtime@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
+  integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-plugin-istanbul "^4.1.6"
+    chalk "^2.0.1"
+    convert-source-map "^1.4.0"
+    exit "^0.1.2"
+    fast-json-stable-stringify "^2.0.0"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    realpath-native "^1.0.0"
+    slash "^1.0.0"
+    strip-bom "3.0.0"
+    write-file-atomic "^2.1.0"
+    yargs "^11.0.0"
+
+jest-serializer@^23.0.1:
+  version "23.0.1"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
+  integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
+
+jest-snapshot@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
+  integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
+  dependencies:
+    babel-types "^6.0.0"
+    chalk "^2.0.1"
+    jest-diff "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-resolve "^23.6.0"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    pretty-format "^23.6.0"
+    semver "^5.5.0"
+
+jest-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
+  integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
+  dependencies:
+    callsites "^2.0.0"
+    chalk "^2.0.1"
+    graceful-fs "^4.1.11"
+    is-ci "^1.0.10"
+    jest-message-util "^23.4.0"
+    mkdirp "^0.5.1"
+    slash "^1.0.0"
+    source-map "^0.6.0"
+
+jest-validate@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
+  integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    leven "^2.1.0"
+    pretty-format "^23.6.0"
+
+jest-watcher@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
+  integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    string-length "^2.0.0"
+
+jest-worker@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
+  integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
+  dependencies:
+    merge-stream "^1.0.1"
 
 jest-worker@^24.6.0:
   version "24.9.0"
@@ -4785,6 +4921,14 @@ jest-worker@^24.6.0:
     merge-stream "^2.0.0"
     supports-color "^6.1.0"
 
+jest@^23.2.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
+  integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+  dependencies:
+    import-local "^1.0.0"
+    jest-cli "^23.6.0"
+
 jquery@^3.3.1:
   version "3.4.1"
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
@@ -4800,7 +4944,7 @@ js-tokens@^3.0.2:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
   integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
 
-js-yaml@^3.13.0, js-yaml@^3.13.1:
+js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.7.0:
   version "3.13.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
   integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@@ -4808,11 +4952,47 @@ js-yaml@^3.13.0, js-yaml@^3.13.1:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
+"jsbn@git+https://github.com/rynomad/jsbn.git":
+  version "0.0.0"
+  resolved "git+https://github.com/rynomad/jsbn.git#bb522b0124f75424f89d49446c40a87111942c7b"
+
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
+jsdom@^11.5.1:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
+  integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
+  dependencies:
+    abab "^2.0.0"
+    acorn "^5.5.3"
+    acorn-globals "^4.1.0"
+    array-equal "^1.0.0"
+    cssom ">= 0.3.2 < 0.4.0"
+    cssstyle "^1.0.0"
+    data-urls "^1.0.0"
+    domexception "^1.0.1"
+    escodegen "^1.9.1"
+    html-encoding-sniffer "^1.0.2"
+    left-pad "^1.3.0"
+    nwsapi "^2.0.7"
+    parse5 "4.0.0"
+    pn "^1.1.0"
+    request "^2.87.0"
+    request-promise-native "^1.0.5"
+    sax "^1.2.4"
+    symbol-tree "^3.2.2"
+    tough-cookie "^2.3.4"
+    w3c-hr-time "^1.0.1"
+    webidl-conversions "^4.0.2"
+    whatwg-encoding "^1.0.3"
+    whatwg-mimetype "^2.1.0"
+    whatwg-url "^6.4.1"
+    ws "^5.2.0"
+    xml-name-validator "^3.0.0"
+
 jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
@@ -4872,13 +5052,6 @@ json5@^2.1.0:
   dependencies:
     minimist "^1.2.0"
 
-jsonfile@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
-  integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
-  optionalDependencies:
-    graceful-fs "^4.1.6"
-
 jsprim@^1.2.2:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -4897,103 +5070,6 @@ jsx-ast-utils@^2.2.3:
     array-includes "^3.0.3"
     object.assign "^4.1.0"
 
-just-extend@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc"
-  integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==
-
-karma-chrome-launcher@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
-  integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==
-  dependencies:
-    fs-access "^1.0.0"
-    which "^1.2.1"
-
-karma-cli@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-1.0.1.tgz#ae6c3c58a313a1d00b45164c455b9b86ce17f960"
-  integrity sha1-rmw8WKMTodALRRZMRVubhs4X+WA=
-  dependencies:
-    resolve "^1.1.6"
-
-karma-logcapture-reporter@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/karma-logcapture-reporter/-/karma-logcapture-reporter-0.0.1.tgz#bf1b0b1c915e0de295a15fe2f0179d4281bacddc"
-  integrity sha1-vxsLHJFeDeKVoV/i8BedQoG6zdw=
-
-karma-mocha@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-1.3.0.tgz#eeaac7ffc0e201eb63c467440d2b69c7cf3778bf"
-  integrity sha1-7qrH/8DiAetjxGdEDStpx883eL8=
-  dependencies:
-    minimist "1.2.0"
-
-karma-sourcemap-loader@^0.3.7:
-  version "0.3.7"
-  resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8"
-  integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=
-  dependencies:
-    graceful-fs "^4.1.2"
-
-karma-spec-reporter@^0.0.31:
-  version "0.0.31"
-  resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3"
-  integrity sha1-SDDccUihVcfXoYbmMjOaDYD63sM=
-  dependencies:
-    colors "^1.1.2"
-
-karma-summary-reporter@^1.5.1:
-  version "1.7.1"
-  resolved "https://registry.yarnpkg.com/karma-summary-reporter/-/karma-summary-reporter-1.7.1.tgz#ff751e6e3950a3b3f2ae96a39b10fdc87938c4db"
-  integrity sha512-1I1njfSKFwogQrfDDyjyXKUeysYdD7SXoXBz2o7oK7RpiGsteyBoV3+6J5qFLcT0D8VGxLzYCsU0BbyeeHIl0g==
-  dependencies:
-    chalk "^1.1.3 || 2.x"
-
-karma-webpack@^4.0.0-beta.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.2.tgz#23219bd95bdda853e3073d3874d34447c77bced0"
-  integrity sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==
-  dependencies:
-    clone-deep "^4.0.1"
-    loader-utils "^1.1.0"
-    neo-async "^2.6.1"
-    schema-utils "^1.0.0"
-    source-map "^0.7.3"
-    webpack-dev-middleware "^3.7.0"
-
-karma@^4.0.1:
-  version "4.4.1"
-  resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.1.tgz#6d9aaab037a31136dc074002620ee11e8c2e32ab"
-  integrity sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==
-  dependencies:
-    bluebird "^3.3.0"
-    body-parser "^1.16.1"
-    braces "^3.0.2"
-    chokidar "^3.0.0"
-    colors "^1.1.0"
-    connect "^3.6.0"
-    di "^0.0.1"
-    dom-serialize "^2.2.0"
-    flatted "^2.0.0"
-    glob "^7.1.1"
-    graceful-fs "^4.1.2"
-    http-proxy "^1.13.0"
-    isbinaryfile "^3.0.0"
-    lodash "^4.17.14"
-    log4js "^4.0.0"
-    mime "^2.3.1"
-    minimatch "^3.0.2"
-    optimist "^0.6.1"
-    qjobs "^1.1.4"
-    range-parser "^1.2.0"
-    rimraf "^2.6.0"
-    safe-buffer "^5.0.1"
-    socket.io "2.1.1"
-    source-map "^0.6.1"
-    tmp "0.0.33"
-    useragent "2.3.0"
-
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -5018,6 +5094,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
   integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
 
+kleur@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
+  integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+
 known-css-properties@^0.11.0:
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a"
@@ -5030,6 +5111,11 @@ lcid@^2.0.0:
   dependencies:
     invert-kv "^2.0.0"
 
+left-pad@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
+  integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
+
 leven@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -5052,6 +5138,17 @@ linkifyjs@^2.1.6:
     react "^16.4.2"
     react-dom "^16.4.2"
 
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
 load-json-file@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
@@ -5114,11 +5211,6 @@ lodash.escaperegexp@^4.1.2:
   resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
   integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
 
-lodash.get@^4.4.2:
-  version "4.4.2"
-  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
-  integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
-
 lodash.isboolean@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
@@ -5144,6 +5236,11 @@ lodash.mergewith@^4.6.1:
   resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
   integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
 
+lodash.sortby@^4.7.0:
+  version "4.7.0"
+  resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+  integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
+
 lodash.unescape@4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
@@ -5161,32 +5258,16 @@ log-symbols@^2.0.0, log-symbols@^2.2.0:
   dependencies:
     chalk "^2.0.1"
 
-log4js@^4.0.0:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5"
-  integrity sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==
-  dependencies:
-    date-format "^2.0.0"
-    debug "^4.1.1"
-    flatted "^2.0.0"
-    rfdc "^1.1.4"
-    streamroller "^1.0.6"
-
 loglevel@^1.6.4:
   version "1.6.6"
   resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312"
   integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==
 
-lolex@4.2, lolex@^4.1.0:
+lolex@4.2:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7"
   integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==
 
-lolex@^2.4.2:
-  version "2.7.5"
-  resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733"
-  integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==
-
 longest-streak@^2.0.1:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.3.tgz#3de7a3f47ee18e9074ded8575b5c091f5d0a4105"
@@ -5207,14 +5288,6 @@ loud-rejection@^1.0.0:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
 
-lru-cache@4.1.x:
-  version "4.1.5"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
-  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
-  dependencies:
-    pseudomap "^1.0.2"
-    yallist "^2.1.2"
-
 lru-cache@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -5254,6 +5327,13 @@ make-fetch-happen@5.0.0:
     socks-proxy-agent "^4.0.0"
     ssri "^6.0.0"
 
+makeerror@1.0.x:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
+  integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=
+  dependencies:
+    tmpl "1.0.x"
+
 mamacro@^0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
@@ -5355,11 +5435,6 @@ mdast-util-compact@^1.0.0:
   resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
   integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
 
-media-typer@0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
-  integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
 mem@^4.0.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
@@ -5410,6 +5485,13 @@ meow@^5.0.0:
     trim-newlines "^2.0.0"
     yargs-parser "^10.0.0"
 
+merge-stream@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+  integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
+  dependencies:
+    readable-stream "^2.0.1"
+
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -5420,7 +5502,12 @@ merge2@^1.2.3:
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
   integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
 
-micromatch@^2.1.5:
+merge@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
+  integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
+
+micromatch@^2.1.5, micromatch@^2.3.11:
   version "2.3.11"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
   integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
@@ -5471,18 +5558,13 @@ mime-db@1.42.0:
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
   integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
 
-mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24:
+mime-types@^2.1.12, mime-types@~2.1.19:
   version "2.1.25"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437"
   integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==
   dependencies:
     mime-db "1.42.0"
 
-mime@^2.3.1, mime@^2.4.4:
-  version "2.4.4"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
-  integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
-
 mimic-fn@^1.0.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
@@ -5503,7 +5585,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
 
-"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -5528,7 +5610,7 @@ minimist@1.1.x:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
   integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=
 
-minimist@1.2.0, minimist@^1.2.0, "minimist@~ 1.2.0":
+minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
@@ -5577,30 +5659,13 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
+mkdirp@^0.5.0, mkdirp@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
   dependencies:
     minimist "0.0.8"
 
-mocha@^5.0.5:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
-  integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
-  dependencies:
-    browser-stdout "1.3.1"
-    commander "2.15.1"
-    debug "3.1.0"
-    diff "3.5.0"
-    escape-string-regexp "1.0.5"
-    glob "7.1.2"
-    growl "1.10.5"
-    he "1.1.1"
-    minimatch "3.0.4"
-    mkdirp "0.5.1"
-    supports-color "5.4.0"
-
 move-concurrently@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -5628,6 +5693,11 @@ mute-stream@0.0.7:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
+nan@^1.6.2:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-1.9.0.tgz#1a9cd2755609766f5c291e4194fce39fde286515"
+  integrity sha1-GpzSdVYJdm9cKR5BlPzjn94oZRU=
+
 nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
@@ -5664,12 +5734,7 @@ needle@^2.2.1:
     iconv-lite "^0.4.4"
     sax "^1.2.4"
 
-negotiator@0.6.2:
-  version "0.6.2"
-  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
-  integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-
-neo-async@^2.5.0, neo-async@^2.6.1:
+neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
   integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
@@ -5679,17 +5744,6 @@ nice-try@^1.0.4:
   resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
   integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
 
-nise@^1.3.3:
-  version "1.5.2"
-  resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.2.tgz#b6d29af10e48b321b307e10e065199338eeb2652"
-  integrity sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==
-  dependencies:
-    "@sinonjs/formatio" "^3.2.1"
-    "@sinonjs/text-encoding" "^0.7.1"
-    just-extend "^4.0.2"
-    lolex "^4.1.0"
-    path-to-regexp "^1.7.0"
-
 node-fetch-npm@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
@@ -5707,6 +5761,16 @@ node-fetch@^1.0.1:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
+node-forge@^0.6.20:
+  version "0.6.49"
+  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.49.tgz#f1ee95d5d74623938fe19d698aa5a26d54d2f60f"
+  integrity sha1-8e6V1ddGI5OP4Z1piqWibVTS9g8=
+
+node-int64@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+  integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
+
 node-libs-browser@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
@@ -5736,6 +5800,33 @@ node-libs-browser@^2.2.1:
     util "^0.11.0"
     vm-browserify "^1.0.1"
 
+node-notifier@^5.2.1:
+  version "5.4.3"
+  resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50"
+  integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==
+  dependencies:
+    growly "^1.3.0"
+    is-wsl "^1.1.0"
+    semver "^5.5.0"
+    shellwords "^0.1.1"
+    which "^1.3.0"
+
+node-pre-gyp@*:
+  version "0.14.0"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
+  integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
+  dependencies:
+    detect-libc "^1.0.2"
+    mkdirp "^0.5.1"
+    needle "^2.2.1"
+    nopt "^4.0.1"
+    npm-packlist "^1.1.6"
+    npmlog "^4.0.2"
+    rc "^1.2.7"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^4.4.2"
+
 node-pre-gyp@^0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
@@ -5784,7 +5875,7 @@ normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
   dependencies:
     remove-trailing-separator "^1.0.1"
 
-normalize-path@^3.0.0, normalize-path@~3.0.0:
+normalize-path@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
   integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
@@ -5829,11 +5920,6 @@ npmlog@^4.0.2:
     gauge "~2.7.3"
     set-blocking "~2.0.0"
 
-null-check@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
-  integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
-
 num2fraction@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
@@ -5844,6 +5930,11 @@ number-is-nan@^1.0.0:
   resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
   integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
 
+nwsapi@^2.0.7:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
+  integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
+
 oauth-sign@~0.9.0:
   version "0.9.0"
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
@@ -5854,11 +5945,6 @@ object-assign@^4.1.0, object-assign@^4.1.1:
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
   integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
 
-object-component@0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
-  integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=
-
 object-copy@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
@@ -5915,6 +6001,14 @@ object.fromentries@^2.0.1:
     function-bind "^1.1.1"
     has "^1.0.3"
 
+object.getownpropertydescriptors@^2.0.3:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649"
+  integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==
+  dependencies:
+    define-properties "^1.1.3"
+    es-abstract "^1.17.0-next.1"
+
 object.omit@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@@ -5940,13 +6034,6 @@ object.values@^1.1.0:
     function-bind "^1.1.1"
     has "^1.0.3"
 
-on-finished@~2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
-  integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
-  dependencies:
-    ee-first "1.1.1"
-
 once@^1.3.0, once@^1.3.1, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -5969,7 +6056,7 @@ optimist@^0.6.1:
     minimist "~0.0.1"
     wordwrap "~0.0.2"
 
-optionator@^0.8.2:
+optionator@^0.8.1, optionator@^0.8.2:
   version "0.8.3"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
   integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -6137,6 +6224,13 @@ parse-glob@^3.0.4:
     is-extglob "^1.0.0"
     is-glob "^2.0.0"
 
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
+  dependencies:
+    error-ex "^1.2.0"
+
 parse-json@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -6150,24 +6244,10 @@ parse-passwd@^1.0.0:
   resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
   integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
 
-parseqs@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
-  integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=
-  dependencies:
-    better-assert "~1.0.0"
-
-parseuri@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
-  integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=
-  dependencies:
-    better-assert "~1.0.0"
-
-parseurl@~1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
-  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+parse5@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
+  integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
 
 pascalcase@^0.1.1:
   version "0.1.1"
@@ -6184,6 +6264,13 @@ path-dirname@^1.0.0:
   resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
   integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
 
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+  dependencies:
+    pinkie-promise "^2.0.0"
+
 path-exists@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -6209,17 +6296,19 @@ path-key@^2.0.0, path-key@^2.0.1:
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
   integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 
-path-parse@^1.0.6:
+path-parse@^1.0.5, path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
 
-path-to-regexp@^1.7.0:
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
-  integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
   dependencies:
-    isarray "0.0.1"
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
 
 path-type@^3.0.0:
   version "3.0.0"
@@ -6249,10 +6338,10 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-picomatch@^2.0.4:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
-  integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+  integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
 
 pify@^3.0.0:
   version "3.0.0"
@@ -6264,6 +6353,18 @@ pify@^4.0.0, pify@^4.0.1:
   resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+  integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+
 pkg-dir@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -6283,6 +6384,11 @@ pluralizers@^0.1.7:
   resolved "https://registry.yarnpkg.com/pluralizers/-/pluralizers-0.1.7.tgz#8d38dd0a1b660e739b10ab2eab10b684c9d50142"
   integrity sha512-mw6AejUiCaMQ6uPN9ObjJDTnR5AnBSmnHHy3uVTbxrSFSxO5scfwpTs8Dxyb6T2v7GSulhvOq+pm9y+hXUvtOA==
 
+pn@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+  integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+
 png-chunks-extract@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz#fad4a905e66652197351c65e35b92c64311e472d"
@@ -6290,6 +6396,13 @@ png-chunks-extract@^1.0.0:
   dependencies:
     crc-32 "^0.3.0"
 
+polyfill-promise@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/polyfill-promise/-/polyfill-promise-4.0.1.tgz#f8448dc27c3b967d5f67fc060f56ed64e2286b49"
+  integrity sha1-+ESNwnw7ln1fZ/wGD1btZOIoa0k=
+  dependencies:
+    bluebird "^2.9.27"
+
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -6418,15 +6531,13 @@ preserve@^0.2.0:
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
   integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
 
-pretty-format@^24.9.0:
-  version "24.9.0"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
-  integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==
+pretty-format@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
   dependencies:
-    "@jest/types" "^24.9.0"
-    ansi-regex "^4.0.0"
+    ansi-regex "^3.0.0"
     ansi-styles "^3.2.0"
-    react-is "^16.8.4"
 
 private@^0.1.6, private@^0.1.8:
   version "0.1.8"
@@ -6468,6 +6579,14 @@ promise@^7.0.3, promise@^7.1.1:
   dependencies:
     asap "~2.0.3"
 
+prompts@^0.1.9:
+  version "0.1.14"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
+  integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+  dependencies:
+    kleur "^2.0.1"
+    sisteransi "^0.1.1"
+
 prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@@ -6482,16 +6601,16 @@ prr@~1.0.1:
   resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
   integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
 
-pseudomap@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
-  integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
 psl@^1.1.24:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.5.0.tgz#47fd1292def7fdb1e138cd78afa8814cebcf7b13"
   integrity sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA==
 
+psl@^1.1.28:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110"
+  integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==
+
 public-encrypt@^4.0.0:
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@@ -6539,15 +6658,22 @@ punycode@^1.2.4, punycode@^1.4.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
   integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
 
-punycode@^2.1.0:
+punycode@^2.1.0, punycode@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
-qjobs@^1.1.4:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
-  integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
+pvtsutils@^1.0.9:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.0.9.tgz#0eb6106f27878ccaa55e7dfbf6bd2c75af461dee"
+  integrity sha512-/kDsuCKPqJuIzn37w6+iN+TiSrN+zrwPEd7FjT61oNbRvceGdsS94fMEWZ4/h6QZU5EZhBMiV+79IYedroP/Yw==
+  dependencies:
+    tslib "^1.10.0"
+
+pvutils@latest:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
+  integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
 
 qr.js@0.0.0:
   version "0.0.0"
@@ -6561,11 +6687,6 @@ qrcode-react@^0.1.16:
   dependencies:
     qr.js "0.0.0"
 
-qs@6.7.0:
-  version "6.7.0"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
-  integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
 qs@^6.5.2, qs@^6.6.0:
   version "6.9.1"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
@@ -6627,21 +6748,6 @@ randomfill@^1.0.3:
     randombytes "^2.0.5"
     safe-buffer "^5.1.0"
 
-range-parser@^1.2.0, range-parser@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
-  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-
-raw-body@2.4.0:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
-  integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
-  dependencies:
-    bytes "3.1.0"
-    http-errors "1.7.2"
-    iconv-lite "0.4.24"
-    unpipe "1.0.0"
-
 rc@1.2.8, rc@^1.2.7, rc@^1.2.8:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -6715,7 +6821,7 @@ react-immutable-proptypes@^2.1.0:
   resolved "https://registry.yarnpkg.com/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz#023d6f39bb15c97c071e9e60d00d136eac5fa0b4"
   integrity sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ=
 
-react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
+react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
   version "16.12.0"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
   integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
@@ -6777,6 +6883,14 @@ react@^16.4.2, react@^16.9.0:
     object-assign "^4.1.1"
     prop-types "^15.6.2"
 
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
 read-pkg-up@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
@@ -6785,6 +6899,15 @@ read-pkg-up@^3.0.0:
     find-up "^2.0.0"
     read-pkg "^3.0.0"
 
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
 read-pkg@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
@@ -6834,12 +6957,12 @@ readdirp@^2.0.0, readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
-readdirp@~3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839"
-  integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==
+realpath-native@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
+  integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
   dependencies:
-    picomatch "^2.0.4"
+    util.promisify "^1.0.0"
 
 redent@^2.0.0:
   version "2.0.0"
@@ -7019,7 +7142,23 @@ replace-ext@1.0.0:
   resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
   integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
 
-request@^2.88.0:
+request-promise-core@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9"
+  integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==
+  dependencies:
+    lodash "^4.17.15"
+
+request-promise-native@^1.0.5:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36"
+  integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==
+  dependencies:
+    request-promise-core "1.1.3"
+    stealthy-require "^1.1.1"
+    tough-cookie "^2.3.3"
+
+request@^2.87.0, request@^2.88.0:
   version "2.88.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
   integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
@@ -7065,11 +7204,6 @@ require-main-filename@^2.0.0:
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
   integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
 
-requires-port@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
-  integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-
 reselect@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
@@ -7110,7 +7244,12 @@ resolve-url@^0.2.1:
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
+resolve@1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+  integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
+
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
   integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
@@ -7135,11 +7274,6 @@ retry@^0.10.0:
   resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
   integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
 
-rfdc@^1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
-  integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-
 rimraf@2.6.3:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@@ -7147,7 +7281,7 @@ rimraf@2.6.3:
   dependencies:
     glob "^7.1.3"
 
-rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.3:
+rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -7180,6 +7314,11 @@ rollup-pluginutils@^2.8.1:
   dependencies:
     estree-walker "^0.6.1"
 
+rsvp@^3.3.3:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
+  integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+
 run-async@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
@@ -7223,10 +7362,21 @@ safe-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-samsam@1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
-  integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==
+sane@^2.0.0:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
+  integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
+  dependencies:
+    anymatch "^2.0.0"
+    capture-exit "^1.2.0"
+    exec-sh "^0.2.0"
+    fb-watchman "^2.0.0"
+    micromatch "^3.1.4"
+    minimist "^1.1.1"
+    walker "~1.0.5"
+    watch "~0.18.0"
+  optionalDependencies:
+    fsevents "^1.2.3"
 
 sanitize-html@^1.18.4:
   version "1.20.1"
@@ -7306,11 +7456,6 @@ setimmediate@^1.0.4, setimmediate@^1.0.5:
   resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
   integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
 
-setprototypeof@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
-  integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
 sha.js@^2.4.0, sha.js@^2.4.8:
   version "2.4.11"
   resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
@@ -7319,13 +7464,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
-shallow-clone@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
-  integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
-  dependencies:
-    kind-of "^6.0.2"
-
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -7338,23 +7476,25 @@ shebang-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
   integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
 
+shellwords@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
+  integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
+
 signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
-sinon@^5.0.7:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.1.1.tgz#19c59810ffb733ea6e76a28b94a71fc4c2f523b8"
-  integrity sha512-h/3uHscbt5pQNxkf7Y/Lb9/OM44YNCicHakcq73ncbrIS8lXg+ZGOZbtuU+/km4YnyiCYfQQEwANaReJz7KDfw==
-  dependencies:
-    "@sinonjs/formatio" "^2.0.0"
-    diff "^3.5.0"
-    lodash.get "^4.4.2"
-    lolex "^2.4.2"
-    nise "^1.3.3"
-    supports-color "^5.4.0"
-    type-detect "^4.0.8"
+sisteransi@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
+  integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
+
+sjcl@^1.0.3:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
+  integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
 
 slash@^1.0.0:
   version "1.0.0"
@@ -7497,52 +7637,6 @@ snapdragon@^0.8.1:
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
-socket.io-adapter@~1.1.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9"
-  integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==
-
-socket.io-client@2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f"
-  integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==
-  dependencies:
-    backo2 "1.0.2"
-    base64-arraybuffer "0.1.5"
-    component-bind "1.0.0"
-    component-emitter "1.2.1"
-    debug "~3.1.0"
-    engine.io-client "~3.2.0"
-    has-binary2 "~1.0.2"
-    has-cors "1.1.0"
-    indexof "0.0.1"
-    object-component "0.0.3"
-    parseqs "0.0.5"
-    parseuri "0.0.5"
-    socket.io-parser "~3.2.0"
-    to-array "0.1.4"
-
-socket.io-parser@~3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077"
-  integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==
-  dependencies:
-    component-emitter "1.2.1"
-    debug "~3.1.0"
-    isarray "2.0.1"
-
-socket.io@2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980"
-  integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==
-  dependencies:
-    debug "~3.1.0"
-    engine.io "~3.2.0"
-    has-binary2 "~1.0.2"
-    socket.io-adapter "~1.1.0"
-    socket.io-client "2.1.1"
-    socket.io-parser "~3.2.0"
-
 socks-proxy-agent@^4.0.0:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
@@ -7590,7 +7684,7 @@ source-map-support@^0.4.15:
   dependencies:
     source-map "^0.5.6"
 
-source-map-support@~0.5.12:
+source-map-support@^0.5.6, source-map-support@~0.5.12:
   version "0.5.16"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
   integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
@@ -7603,7 +7697,7 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
-source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -7613,11 +7707,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 
-source-map@^0.7.3:
-  version "0.7.3"
-  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
-  integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
-
 spawn-command@^0.0.2-1:
   version "0.0.2-1"
   resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
@@ -7719,10 +7808,10 @@ static-extend@^0.1.1:
     define-property "^0.2.5"
     object-copy "^0.1.0"
 
-"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
-  integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+stealthy-require@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+  integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
 
 stream-browserify@^2.0.1:
   version "2.0.2"
@@ -7756,16 +7845,13 @@ stream-shift@^1.0.0:
   resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
   integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
 
-streamroller@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
-  integrity sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==
+string-length@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
+  integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=
   dependencies:
-    async "^2.6.2"
-    date-format "^2.0.0"
-    debug "^3.2.6"
-    fs-extra "^7.0.1"
-    lodash "^4.17.14"
+    astral-regex "^1.0.0"
+    strip-ansi "^4.0.0"
 
 string-width@4.1.0:
   version "4.1.0"
@@ -7868,11 +7954,18 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
-strip-bom@^3.0.0:
+strip-bom@3.0.0, strip-bom@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
   integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
 
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+  dependencies:
+    is-utf8 "^0.2.0"
+
 strip-eof@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -7971,6 +8064,18 @@ stylelint@^9.10.1:
     svg-tags "^1.0.0"
     table "^5.0.0"
 
+subtle@^0.1.8:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/subtle/-/subtle-0.1.8.tgz#0c12599b9cf13127eda11626510cd8f24f878916"
+  integrity sha1-DBJZm5zxMSftoRYmUQzY8k+HiRY=
+  dependencies:
+    ecc-jsbn "0.0.1"
+    node-forge "^0.6.20"
+    polyfill-promise "^4.0.1"
+    sjcl "^1.0.3"
+  optionalDependencies:
+    ecc-qj "git+https://github.com/rynomad/ecc.git"
+
 sugarss@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
@@ -7978,13 +8083,6 @@ sugarss@^2.0.0:
   dependencies:
     postcss "^7.0.2"
 
-supports-color@5.4.0:
-  version "5.4.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
-  integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
-  dependencies:
-    has-flag "^3.0.0"
-
 supports-color@6.1.0, supports-color@^6.1.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
@@ -7997,6 +8095,13 @@ supports-color@^2.0.0:
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
   integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
 
+supports-color@^3.1.2:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+  dependencies:
+    has-flag "^1.0.0"
+
 supports-color@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
@@ -8004,7 +8109,7 @@ supports-color@^4.5.0:
   dependencies:
     has-flag "^2.0.0"
 
-supports-color@^5.3.0, supports-color@^5.4.0:
+supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
   integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@@ -8021,6 +8126,11 @@ symbol-observable@^1.0.3:
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
   integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
 
+symbol-tree@^3.2.2:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+  integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
 table@^5.0.0, table@^5.2.3:
   version "5.4.6"
   resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@@ -8036,7 +8146,7 @@ tapable@^1.0.0, tapable@^1.1.3:
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
   integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 
-tar@^4:
+tar@^4, tar@^4.4.2:
   version "4.4.13"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
   integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
@@ -8073,6 +8183,17 @@ terser@^4.1.0, terser@^4.1.2:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
+test-exclude@^4.2.1:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
+  integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+  dependencies:
+    arrify "^1.0.1"
+    micromatch "^2.3.11"
+    object-assign "^4.1.0"
+    read-pkg-up "^1.0.1"
+    require-main-filename "^1.0.1"
+
 text-encoding-utf-8@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
@@ -8083,6 +8204,11 @@ text-table@0.2.0, text-table@^0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
   integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
 
+throat@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
+  integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
+
 through2@^2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -8108,17 +8234,17 @@ tmatch@^2.0.1:
   resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf"
   integrity sha1-DFYkbzPzDaG409colauvFmYPOM8=
 
-tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
+tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
   integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
   dependencies:
     os-tmpdir "~1.0.2"
 
-to-array@0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
-  integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
+tmpl@1.0.x:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
+  integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
 
 to-arraybuffer@^1.0.0:
   version "1.0.1"
@@ -8150,13 +8276,6 @@ to-regex-range@^2.1.0:
     is-number "^3.0.0"
     repeat-string "^1.6.1"
 
-to-regex-range@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
-  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
-  dependencies:
-    is-number "^7.0.0"
-
 to-regex@^3.0.1, to-regex@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@@ -8167,10 +8286,13 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
-toidentifier@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
-  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+tough-cookie@^2.3.3, tough-cookie@^2.3.4:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+  integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+  dependencies:
+    psl "^1.1.28"
+    punycode "^2.1.1"
 
 tough-cookie@~2.4.3:
   version "2.4.3"
@@ -8180,6 +8302,13 @@ tough-cookie@~2.4.3:
     psl "^1.1.24"
     punycode "^1.4.1"
 
+tr46@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+  integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
+  dependencies:
+    punycode "^2.1.0"
+
 tree-kill@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a"
@@ -8210,7 +8339,7 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
@@ -8246,19 +8375,6 @@ type-check@~0.3.2:
   dependencies:
     prelude-ls "~1.1.2"
 
-type-detect@4.0.8, type-detect@^4.0.8:
-  version "4.0.8"
-  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
-  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-
-type-is@~1.6.17:
-  version "1.6.18"
-  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
-  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
-  dependencies:
-    media-typer "0.3.0"
-    mime-types "~2.1.24"
-
 type-of@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/type-of/-/type-of-2.0.1.tgz#e72a1741896568e9f628378d816d6912f7f23972"
@@ -8274,10 +8390,13 @@ ua-parser-js@^0.7.18:
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
   integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
 
-ultron@~1.1.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
-  integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
+uglify-js@^3.1.4:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9"
+  integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==
+  dependencies:
+    commander "~2.20.3"
+    source-map "~0.6.1"
 
 unherit@^1.0.4:
   version "1.1.2"
@@ -8380,16 +8499,6 @@ unist-util-visit@^1.1.0:
   dependencies:
     unist-util-visit-parents "^2.0.0"
 
-universalify@^0.1.0:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
-  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-unpipe@1.0.0, unpipe@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
-  integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
 unset-value@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@@ -8462,19 +8571,19 @@ user-home@^1.1.1:
   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
   integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA=
 
-useragent@2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
-  integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==
-  dependencies:
-    lru-cache "4.1.x"
-    tmp "0.0.x"
-
 util-deprecate@^1.0.1, util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
   integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
 
+util.promisify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+  integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
+  dependencies:
+    define-properties "^1.1.2"
+    object.getownpropertydescriptors "^2.0.3"
+
 util@0.10.3:
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
@@ -8489,11 +8598,6 @@ util@^0.11.0:
   dependencies:
     inherits "2.0.3"
 
-utils-merge@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
-  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-
 uuid@^3.3.2:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
@@ -8568,10 +8672,12 @@ vm-browserify@^1.0.1:
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
   integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
 
-void-elements@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
-  integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
+w3c-hr-time@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
+  integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=
+  dependencies:
+    browser-process-hrtime "^0.1.2"
 
 walk@^2.3.9:
   version "2.3.14"
@@ -8580,6 +8686,13 @@ walk@^2.3.9:
   dependencies:
     foreachasync "^3.0.0"
 
+walker@~1.0.5:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
+  integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
+  dependencies:
+    makeerror "1.0.x"
+
 warning@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
@@ -8587,6 +8700,14 @@ warning@^3.0.0:
   dependencies:
     loose-envify "^1.0.0"
 
+watch@~0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
+  integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
+  dependencies:
+    exec-sh "^0.2.0"
+    minimist "^1.2.0"
+
 watchpack@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
@@ -8596,6 +8717,19 @@ watchpack@^1.6.0:
     graceful-fs "^4.1.2"
     neo-async "^2.5.0"
 
+webcrypto-core@^1.0.17:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.0.17.tgz#a9354bc0b1ba6735e882f4137ede2c4366e6ad9b"
+  integrity sha512-7jxTLgtM+TahBPErx/Dd2XvxFDfWJrHxjVeTSvIa4LSgiYrmCPlC2INiAMAfb8MbtHiwJKKqF5sPS0AWNjBbXw==
+  dependencies:
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
+
+webidl-conversions@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+  integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
 webpack-cli@^3.1.1:
   version "3.3.10"
   resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13"
@@ -8613,25 +8747,6 @@ webpack-cli@^3.1.1:
     v8-compile-cache "2.0.3"
     yargs "13.2.4"
 
-webpack-dev-middleware@^3.7.0:
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
-  integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
-  dependencies:
-    memory-fs "^0.4.1"
-    mime "^2.4.4"
-    mkdirp "^0.5.1"
-    range-parser "^1.2.1"
-    webpack-log "^2.0.0"
-
-webpack-log@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
-  integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
-  dependencies:
-    ansi-colors "^3.0.0"
-    uuid "^3.3.2"
-
 webpack-sources@^1.4.0, webpack-sources@^1.4.1:
   version "1.4.3"
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
@@ -8674,6 +8789,13 @@ what-input@^5.2.6:
   resolved "https://registry.yarnpkg.com/what-input/-/what-input-5.2.6.tgz#ac6f003bf8d3592a0031dea7a03565469b00020b"
   integrity sha512-a0BcI5YR7xp87vSzGcbN0IszJKpUQuTmrZaTSQBl7TLDIdKj6rDhluQ7b/7lYGG81gWDvkySsEvwv4BW5an9kg==
 
+whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+  integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+  dependencies:
+    iconv-lite "0.4.24"
+
 whatwg-fetch@>=0.10.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
@@ -8689,6 +8811,29 @@ whatwg-fetch@^1.1.1:
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319"
   integrity sha1-rDydOfMgxtzlM5lp0FTvQ90zMxk=
 
+whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+  integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^6.4.1:
+  version "6.5.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
+  integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
+whatwg-url@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+  integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
 which-boxed-primitive@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1"
@@ -8715,7 +8860,7 @@ which-module@^2.0.0:
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1:
+which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -8768,6 +8913,15 @@ wrappy@1:
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 
+write-file-atomic@^2.1.0:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+  integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+  dependencies:
+    graceful-fs "^4.1.11"
+    imurmurhash "^0.1.4"
+    signal-exit "^3.0.2"
+
 write@1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
@@ -8775,40 +8929,38 @@ write@1.0.3:
   dependencies:
     mkdirp "^0.5.1"
 
-ws@~3.3.1:
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
-  integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
+ws@^5.2.0:
+  version "5.2.2"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
+  integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
   dependencies:
     async-limiter "~1.0.0"
-    safe-buffer "~5.1.0"
-    ultron "~1.1.0"
 
 x-is-string@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
   integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
 
-xmlhttprequest-ssl@~1.5.4:
-  version "1.5.5"
-  resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
-  integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
+xml-name-validator@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+  integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
 
 xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
   integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
 
+y18n@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+  integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
+
 "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
   integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
 
-yallist@^2.1.2:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
-  integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
 yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
@@ -8837,6 +8989,13 @@ yargs-parser@^13.1.0:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
+yargs-parser@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+  integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
+  dependencies:
+    camelcase "^4.1.0"
+
 yargs@13.2.4:
   version "13.2.4"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
@@ -8854,6 +9013,24 @@ yargs@13.2.4:
     y18n "^4.0.0"
     yargs-parser "^13.1.0"
 
+yargs@^11.0.0:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
+  integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^1.1.1"
+    find-up "^2.1.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.1.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^9.0.2"
+
 yargs@^12.0.5:
   version "12.0.5"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
@@ -8872,11 +9049,6 @@ yargs@^12.0.5:
     y18n "^3.2.1 || ^4.0.0"
     yargs-parser "^11.1.1"
 
-yeast@0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
-  integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
-
 zxcvbn@^4.4.2:
   version "4.4.2"
   resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"

From e7928e8def9d80b9df06aec87433cb77acd15e68 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sun, 22 Dec 2019 20:56:19 -0700
Subject: [PATCH 29/86] Use `flex-start` instead of `start` for postcss

This is just something the loaders complain about - apparently `start` is old and we should feel bad.
---
 res/css/views/context_menus/_StatusMessageContextMenu.scss      | 2 +-
 res/css/views/dialogs/_CreateRoomDialog.scss                    | 2 +-
 res/css/views/dialogs/keybackup/_CreateKeyBackupDialog.scss     | 2 +-
 .../views/dialogs/secretstorage/_CreateSecretStorageDialog.scss | 2 +-
 res/css/views/rooms/_MemberDeviceInfo.scss                      | 2 +-
 res/css/views/rooms/_MessageComposer.scss                       | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/res/css/views/context_menus/_StatusMessageContextMenu.scss b/res/css/views/context_menus/_StatusMessageContextMenu.scss
index 972f608caf..2c8d608950 100644
--- a/res/css/views/context_menus/_StatusMessageContextMenu.scss
+++ b/res/css/views/context_menus/_StatusMessageContextMenu.scss
@@ -61,5 +61,5 @@ input.mx_StatusMessageContextMenu_message {
 }
 
 .mx_StatusMessageContextMenu_actionContainer .mx_Spinner {
-    justify-content: start;
+    justify-content: flex-start;
 }
diff --git a/res/css/views/dialogs/_CreateRoomDialog.scss b/res/css/views/dialogs/_CreateRoomDialog.scss
index d3a8f6ff42..7416ec2ef4 100644
--- a/res/css/views/dialogs/_CreateRoomDialog.scss
+++ b/res/css/views/dialogs/_CreateRoomDialog.scss
@@ -30,7 +30,7 @@ limitations under the License.
 
     > div {
         display: flex;
-        align-items: start;
+        align-items: flex-start;
         margin: 5px 0;
 
         input[type=checkbox] {
diff --git a/res/css/views/dialogs/keybackup/_CreateKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_CreateKeyBackupDialog.scss
index 7ba5f01a76..04ee575867 100644
--- a/res/css/views/dialogs/keybackup/_CreateKeyBackupDialog.scss
+++ b/res/css/views/dialogs/keybackup/_CreateKeyBackupDialog.scss
@@ -32,7 +32,7 @@ limitations under the License.
 
 .mx_CreateKeyBackupDialog_passPhraseContainer {
     display: flex;
-    align-items: start;
+    align-items: flex-start;
 }
 
 .mx_CreateKeyBackupDialog_passPhraseHelp {
diff --git a/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss b/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss
index 757d8028f0..5899abdf73 100644
--- a/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss
+++ b/res/css/views/dialogs/secretstorage/_CreateSecretStorageDialog.scss
@@ -33,7 +33,7 @@ limitations under the License.
 
 .mx_CreateSecretStorageDialog_passPhraseContainer {
     display: flex;
-    align-items: start;
+    align-items: flex-start;
 }
 
 .mx_CreateSecretStorageDialog_passPhraseHelp {
diff --git a/res/css/views/rooms/_MemberDeviceInfo.scss b/res/css/views/rooms/_MemberDeviceInfo.scss
index e73e6c58f1..15b4832dc5 100644
--- a/res/css/views/rooms/_MemberDeviceInfo.scss
+++ b/res/css/views/rooms/_MemberDeviceInfo.scss
@@ -17,7 +17,7 @@ limitations under the License.
 .mx_MemberDeviceInfo {
     display: flex;
     padding-bottom: 10px;
-    align-items: start;
+    align-items: flex-start;
 }
 
 .mx_MemberDeviceInfo_icon {
diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss
index 12e45a07c9..5efca51844 100644
--- a/res/css/views/rooms/_MessageComposer.scss
+++ b/res/css/views/rooms/_MessageComposer.scss
@@ -101,7 +101,7 @@ limitations under the License.
     display: flex;
     flex-direction: column;
     min-height: 60px;
-    justify-content: start;
+    justify-content: flex-start;
     align-items: flex-start;
     font-size: 14px;
     margin-right: 6px;

From 0b0fe92b1767771b1666c0c4e6fdd5a58b534be0 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 17 Dec 2019 12:51:09 -0700
Subject: [PATCH 30/86] Convert resizer to ES6

---
 src/resizer/index.js | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/src/resizer/index.js b/src/resizer/index.js
index bc4c8f388c..7c4b2bd493 100644
--- a/src/resizer/index.js
+++ b/src/resizer/index.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,14 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import FixedDistributor from "./distributors/fixed";
-import CollapseDistributor from "./distributors/collapse";
-import RoomSubListDistributor from "./distributors/roomsublist";
-import Resizer from "./resizer";
-
-module.exports = {
-    Resizer,
-    FixedDistributor,
-    CollapseDistributor,
-    RoomSubListDistributor,
-};
+export FixedDistributor from "./distributors/fixed";
+export CollapseDistributor from "./distributors/collapse";
+export RoomSubListDistributor from "./distributors/roomsublist";
+export Resizer from "./resizer";

From 344dac4fb984f42e9881f5d6267e1448fe3e319e Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 17:45:24 -0700
Subject: [PATCH 31/86] Convert CommonJS exports to ES6-compatible exports

We use `export default` begrudgingly here. Ideally we'd use just `export`, though this entire SDK expects things to be exported as a default. Instead of breaking everything, we'll sacrifice our export pattern for a smaller diff - a later commit can always do the default export -> regular export conversion.
---
 src/Analytics.js                              |   2 +-
 src/Avatar.js                                 | 204 +++++++++---------
 src/CallHandler.js                            |   2 +-
 src/Entities.js                               |  59 +++--
 src/ImageUtils.js                             |  71 +++---
 src/Notifier.js                               |   2 +-
 src/PasswordReset.js                          |   3 +-
 src/PlatformPeg.js                            |   2 +-
 src/Presence.js                               |   3 +-
 src/RoomListSorter.js                         |   6 +-
 src/ScalarMessaging.js                        |  49 +++--
 src/Skinner.js                                |   2 +-
 src/TextForEvent.js                           |  12 +-
 src/Unread.js                                 | 140 ++++++------
 src/WhoIsTyping.js                            | 108 +++++-----
 .../views/dialogs/EncryptedEventDialog.js     |   2 +-
 .../structures/CompatibilityPage.js           |   3 +-
 src/components/structures/FilePanel.js        |   3 +-
 src/components/structures/LeftPanel.js        |   2 +-
 .../structures/NotificationPanel.js           |   3 +-
 src/components/structures/RoomDirectory.js    |   2 +-
 src/components/structures/RoomStatusBar.js    |   3 +-
 src/components/structures/RoomView.js         |   2 +-
 src/components/structures/ScrollPanel.js      |   2 +-
 src/components/structures/SearchBox.js        |   2 +-
 src/components/structures/TimelinePanel.js    |   2 +-
 src/components/structures/UploadBar.js        |   3 +-
 src/components/structures/ViewSource.js       |   3 +-
 .../structures/auth/ForgotPassword.js         |   2 +-
 src/components/structures/auth/Login.js       |   2 +-
 .../structures/auth/PostRegistration.js       |   2 +-
 .../structures/auth/Registration.js           |   2 +-
 src/components/views/auth/AuthFooter.js       |   3 +-
 src/components/views/auth/AuthHeader.js       |   2 +-
 src/components/views/auth/CaptchaForm.js      |   2 +-
 .../views/auth/CustomServerDialog.js          |   2 +-
 src/components/views/auth/RegistrationForm.js |   2 +-
 src/components/views/avatars/BaseAvatar.js    |   3 +-
 src/components/views/avatars/MemberAvatar.js  |   3 +-
 src/components/views/avatars/RoomAvatar.js    |   2 +-
 .../views/context_menus/MessageContextMenu.js |   2 +-
 .../context_menus/RoomTileContextMenu.js      |   2 +-
 .../views/create_room/CreateRoomButton.js     |   3 +-
 src/components/views/create_room/Presets.js   |   3 +-
 src/components/views/create_room/RoomAlias.js |   3 +-
 .../views/dialogs/AddressPickerDialog.js      |   2 +-
 .../views/elements/DialogButtons.js           |   3 +-
 src/components/views/elements/EditableText.js |   2 +-
 .../views/elements/InlineSpinner.js           |   2 +-
 .../views/elements/MemberEventListSummary.js  |   2 +-
 .../views/elements/MessageSpinner.js          |   2 +-
 .../views/elements/PersistentApp.js           |   3 +-
 .../views/elements/PowerSelector.js           |   2 +-
 src/components/views/elements/ProgressBar.js  |   3 +-
 src/components/views/elements/SettingsFlag.js |   3 +-
 src/components/views/elements/Spinner.js      |   3 +-
 src/components/views/elements/TintableSvg.js  |   3 +-
 src/components/views/elements/Tooltip.js      |   3 +-
 .../views/elements/TooltipButton.js           |   2 +-
 .../views/elements/TruncatedList.js           |   2 +-
 src/components/views/elements/UserSelector.js |   3 +-
 src/components/views/globals/MatrixToolbar.js |   2 +-
 .../views/groups/GroupMemberInfo.js           |   3 +-
 src/components/views/groups/GroupRoomInfo.js  |   3 +-
 src/components/views/messages/MFileBody.js    |   2 +-
 src/components/views/messages/MVideoBody.js   |   3 +-
 src/components/views/messages/MessageEvent.js |   2 +-
 .../views/messages/RoomAvatarEvent.js         |   3 +-
 src/components/views/messages/RoomCreate.js   |   3 +-
 src/components/views/messages/TextualBody.js  |   2 +-
 src/components/views/messages/TextualEvent.js |   3 +-
 src/components/views/messages/UnknownBody.js  |   2 +-
 .../views/room_settings/ColorSettings.js      |   2 +-
 .../views/room_settings/UrlPreviewSettings.js |   5 +-
 src/components/views/rooms/AppsDrawer.js      |   2 +-
 src/components/views/rooms/AuxPanel.js        |   2 +-
 src/components/views/rooms/EventTile.js       |   2 +-
 src/components/views/rooms/ForwardMessage.js  |   2 +-
 .../views/rooms/LinkPreviewWidget.js          |   3 +-
 src/components/views/rooms/MemberInfo.js      |   2 +-
 src/components/views/rooms/MemberList.js      |   2 +-
 src/components/views/rooms/MemberTile.js      |   3 +-
 src/components/views/rooms/PinnedEventTile.js |   2 +-
 .../views/rooms/PinnedEventsPanel.js          |   3 +-
 src/components/views/rooms/PresenceLabel.js   |   2 +-
 .../views/rooms/ReadReceiptMarker.js          |   3 +-
 src/components/views/rooms/RoomDropTarget.js  |   3 +-
 src/components/views/rooms/RoomHeader.js      |   3 +-
 src/components/views/rooms/RoomList.js        |   2 +-
 src/components/views/rooms/RoomNameEditor.js  |   2 +-
 src/components/views/rooms/RoomPreviewBar.js  |   2 +-
 src/components/views/rooms/RoomTile.js        |   2 +-
 src/components/views/rooms/RoomTopicEditor.js |   2 +-
 .../views/rooms/RoomUpgradeWarningBar.js      |   2 +-
 src/components/views/rooms/SearchBar.js       |   2 +-
 .../views/rooms/SearchResultTile.js           |   3 +-
 .../views/rooms/SearchableEntityList.js       |   3 +-
 .../views/rooms/TopUnreadMessagesBar.js       |   2 +-
 src/components/views/rooms/UserTile.js        |   3 +-
 src/components/views/rooms/WhoIsTypingTile.js |   2 +-
 src/components/views/settings/ChangeAvatar.js |   2 +-
 .../views/settings/ChangeDisplayName.js       |   3 +-
 .../views/settings/ChangePassword.js          |   2 +-
 .../settings/EnableNotificationsButton.js     |   2 +-
 .../views/settings/Notifications.js           |   2 +-
 src/components/views/voip/CallPreview.js      |   3 +-
 src/components/views/voip/CallView.js         |   3 +-
 src/components/views/voip/IncomingCallBox.js  |   3 +-
 src/components/views/voip/VideoFeed.js        |   3 +-
 src/components/views/voip/VideoView.js        |   3 +-
 src/createRoom.js                             |   4 +-
 src/dispatcher.js                             |   2 +-
 src/email.js                                  |   8 +-
 src/extend.js                                 |   4 +-
 src/indexing/EventIndexPeg.js                 |   2 +-
 src/notifications/ContentRules.js             |  15 +-
 src/notifications/NotificationUtils.js        |  13 +-
 src/notifications/PushRuleVectorState.js      |  55 +++--
 src/notifications/StandardActions.js          |  21 +-
 .../VectorPushRulesDefinitions.js             |  14 +-
 src/notifications/index.js                    |  11 +-
 src/rageshake/rageshake.js                    | 136 ++++++------
 src/rageshake/submit-rageshake.js             |   2 +-
 src/stores/GroupStore.js                      |   2 +-
 src/stores/LifecycleStore.js                  |   3 +-
 src/stores/MessageComposerStore.js            |   3 +-
 src/stores/RoomViewStore.js                   |   3 +-
 src/stores/SessionStore.js                    |   3 +-
 src/stores/WidgetEchoStore.js                 |   3 +-
 test/components/stub-component.js             |   2 +-
 test/end-to-end-tests/src/logbuffer.js        |   3 +-
 test/end-to-end-tests/src/logger.js           |   3 +-
 test/end-to-end-tests/src/rest/creator.js     |   3 +-
 test/end-to-end-tests/src/rest/multi.js       |   3 +-
 test/end-to-end-tests/src/rest/room.js        |   3 +-
 test/end-to-end-tests/src/rest/session.js     |   2 +-
 .../src/scenarios/directory.js                |   3 +-
 .../src/scenarios/e2e-encryption.js           |   3 +-
 .../src/scenarios/lazy-loading.js             |   3 +-
 test/end-to-end-tests/src/session.js          |   3 +-
 .../src/usecases/accept-invite.js             |   3 +-
 .../src/usecases/create-room.js               |   7 +-
 test/end-to-end-tests/src/usecases/dialog.js  |  13 +-
 test/end-to-end-tests/src/usecases/invite.js  |   3 +-
 test/end-to-end-tests/src/usecases/join.js    |   3 +-
 .../src/usecases/room-settings.js             |   3 +-
 test/end-to-end-tests/src/usecases/signup.js  |   3 +-
 147 files changed, 649 insertions(+), 620 deletions(-)

diff --git a/src/Analytics.js b/src/Analytics.js
index 3e208ad6bd..3d28a236b0 100644
--- a/src/Analytics.js
+++ b/src/Analytics.js
@@ -306,4 +306,4 @@ class Analytics {
 if (!global.mxAnalytics) {
     global.mxAnalytics = new Analytics();
 }
-module.exports = global.mxAnalytics;
+export default global.mxAnalytics;
diff --git a/src/Avatar.js b/src/Avatar.js
index 17860698cb..3377849eca 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -19,116 +19,114 @@ import {ContentRepo} from 'matrix-js-sdk';
 import MatrixClientPeg from './MatrixClientPeg';
 import DMRoomMap from './utils/DMRoomMap';
 
-module.exports = {
-    avatarUrlForMember: function(member, width, height, resizeMethod) {
-        let url = member.getAvatarUrl(
-            MatrixClientPeg.get().getHomeserverUrl(),
-            Math.floor(width * window.devicePixelRatio),
-            Math.floor(height * window.devicePixelRatio),
-            resizeMethod,
-            false,
-            false,
-        );
-        if (!url) {
-            // member can be null here currently since on invites, the JS SDK
-            // does not have enough info to build a RoomMember object for
-            // the inviter.
-            url = this.defaultAvatarUrlForString(member ? member.userId : '');
+export function avatarUrlForMember(member, width, height, resizeMethod) {
+    let url = member.getAvatarUrl(
+        MatrixClientPeg.get().getHomeserverUrl(),
+        Math.floor(width * window.devicePixelRatio),
+        Math.floor(height * window.devicePixelRatio),
+        resizeMethod,
+        false,
+        false,
+    );
+    if (!url) {
+        // member can be null here currently since on invites, the JS SDK
+        // does not have enough info to build a RoomMember object for
+        // the inviter.
+        url = this.defaultAvatarUrlForString(member ? member.userId : '');
+    }
+    return url;
+}
+
+export function avatarUrlForUser(user, width, height, resizeMethod) {
+    const url = ContentRepo.getHttpUriForMxc(
+        MatrixClientPeg.get().getHomeserverUrl(), user.avatarUrl,
+        Math.floor(width * window.devicePixelRatio),
+        Math.floor(height * window.devicePixelRatio),
+        resizeMethod,
+    );
+    if (!url || url.length === 0) {
+        return null;
+    }
+    return url;
+}
+
+export function defaultAvatarUrlForString(s) {
+    const images = ['03b381', '368bd6', 'ac3ba8'];
+    let total = 0;
+    for (let i = 0; i < s.length; ++i) {
+        total += s.charCodeAt(i);
+    }
+    return require('../res/img/' + images[total % images.length] + '.png');
+}
+
+/**
+ * returns the first (non-sigil) character of 'name',
+ * converted to uppercase
+ * @param {string} name
+ * @return {string} the first letter
+ */
+export function getInitialLetter(name) {
+    if (!name) {
+        // XXX: We should find out what causes the name to sometimes be falsy.
+        console.trace("`name` argument to `getInitialLetter` not supplied");
+        return undefined;
+    }
+    if (name.length < 1) {
+        return undefined;
+    }
+
+    let idx = 0;
+    const initial = name[0];
+    if ((initial === '@' || initial === '#' || initial === '+') && name[1]) {
+        idx++;
+    }
+
+    // string.codePointAt(0) would do this, but that isn't supported by
+    // some browsers (notably PhantomJS).
+    let chars = 1;
+    const first = name.charCodeAt(idx);
+
+    // check if it’s the start of a surrogate pair
+    if (first >= 0xD800 && first <= 0xDBFF && name[idx+1]) {
+        const second = name.charCodeAt(idx+1);
+        if (second >= 0xDC00 && second <= 0xDFFF) {
+            chars++;
         }
-        return url;
-    },
+    }
 
-    avatarUrlForUser: function(user, width, height, resizeMethod) {
-        const url = ContentRepo.getHttpUriForMxc(
-            MatrixClientPeg.get().getHomeserverUrl(), user.avatarUrl,
-            Math.floor(width * window.devicePixelRatio),
-            Math.floor(height * window.devicePixelRatio),
-            resizeMethod,
-        );
-        if (!url || url.length === 0) {
-            return null;
-        }
-        return url;
-    },
+    const firstChar = name.substring(idx, idx+chars);
+    return firstChar.toUpperCase();
+}
 
-    defaultAvatarUrlForString: function(s) {
-        const images = ['03b381', '368bd6', 'ac3ba8'];
-        let total = 0;
-        for (let i = 0; i < s.length; ++i) {
-            total += s.charCodeAt(i);
-        }
-        return require('../res/img/' + images[total % images.length] + '.png');
-    },
+export function avatarUrlForRoom(room, width, height, resizeMethod) {
+    const explicitRoomAvatar = room.getAvatarUrl(
+        MatrixClientPeg.get().getHomeserverUrl(),
+        width,
+        height,
+        resizeMethod,
+        false,
+    );
+    if (explicitRoomAvatar) {
+        return explicitRoomAvatar;
+    }
 
-    /**
-     * returns the first (non-sigil) character of 'name',
-     * converted to uppercase
-     * @param {string} name
-     * @return {string} the first letter
-     */
-    getInitialLetter(name) {
-        if (!name) {
-            // XXX: We should find out what causes the name to sometimes be falsy.
-            console.trace("`name` argument to `getInitialLetter` not supplied");
-            return undefined;
-        }
-        if (name.length < 1) {
-            return undefined;
-        }
-
-        let idx = 0;
-        const initial = name[0];
-        if ((initial === '@' || initial === '#' || initial === '+') && name[1]) {
-            idx++;
-        }
-
-        // string.codePointAt(0) would do this, but that isn't supported by
-        // some browsers (notably PhantomJS).
-        let chars = 1;
-        const first = name.charCodeAt(idx);
-
-        // check if it’s the start of a surrogate pair
-        if (first >= 0xD800 && first <= 0xDBFF && name[idx+1]) {
-            const second = name.charCodeAt(idx+1);
-            if (second >= 0xDC00 && second <= 0xDFFF) {
-                chars++;
-            }
-        }
-
-        const firstChar = name.substring(idx, idx+chars);
-        return firstChar.toUpperCase();
-    },
-
-    avatarUrlForRoom(room, width, height, resizeMethod) {
-        const explicitRoomAvatar = room.getAvatarUrl(
+    let otherMember = null;
+    const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
+    if (otherUserId) {
+        otherMember = room.getMember(otherUserId);
+    } else {
+        // if the room is not marked as a 1:1, but only has max 2 members
+        // then still try to show any avatar (pref. other member)
+        otherMember = room.getAvatarFallbackMember();
+    }
+    if (otherMember) {
+        return otherMember.getAvatarUrl(
             MatrixClientPeg.get().getHomeserverUrl(),
             width,
             height,
             resizeMethod,
             false,
         );
-        if (explicitRoomAvatar) {
-            return explicitRoomAvatar;
-        }
-
-        let otherMember = null;
-        const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
-        if (otherUserId) {
-            otherMember = room.getMember(otherUserId);
-        } else {
-            // if the room is not marked as a 1:1, but only has max 2 members
-            // then still try to show any avatar (pref. other member)
-            otherMember = room.getAvatarFallbackMember();
-        }
-        if (otherMember) {
-            return otherMember.getAvatarUrl(
-                MatrixClientPeg.get().getHomeserverUrl(),
-                width,
-                height,
-                resizeMethod,
-                false,
-            );
-        }
-        return null;
-    },
-};
+    }
+    return null;
+}
diff --git a/src/CallHandler.js b/src/CallHandler.js
index ecbf6c2c12..eb5a5c1c8e 100644
--- a/src/CallHandler.js
+++ b/src/CallHandler.js
@@ -583,4 +583,4 @@ if (global.mxCallHandler === undefined) {
     global.mxCallHandler = callHandler;
 }
 
-module.exports = global.mxCallHandler;
+export default global.mxCallHandler;
diff --git a/src/Entities.js b/src/Entities.js
index 8be1da0db8..0906bef5de 100644
--- a/src/Entities.js
+++ b/src/Entities.js
@@ -105,36 +105,33 @@ class UserEntity extends Entity {
     }
 }
 
+export function newEntity(jsx, matchFn) {
+    const entity = new Entity();
+    entity.getJsx = function() {
+        return jsx;
+    };
+    entity.matches = matchFn;
+    return entity;
+}
 
-module.exports = {
-    newEntity: function(jsx, matchFn) {
-        const entity = new Entity();
-        entity.getJsx = function() {
-            return jsx;
-        };
-        entity.matches = matchFn;
-        return entity;
-    },
+/**
+ * @param {RoomMember[]} members
+ * @return {Entity[]}
+ */
+export function fromRoomMembers(members) {
+    return members.map(function(m) {
+        return new MemberEntity(m);
+    });
+}
 
-    /**
-     * @param {RoomMember[]} members
-     * @return {Entity[]}
-     */
-    fromRoomMembers: function(members) {
-        return members.map(function(m) {
-            return new MemberEntity(m);
-        });
-    },
-
-    /**
-     * @param {User[]} users
-     * @param {boolean} showInviteButton
-     * @param {Function} inviteFn Called with the user ID.
-     * @return {Entity[]}
-     */
-    fromUsers: function(users, showInviteButton, inviteFn) {
-        return users.map(function(u) {
-            return new UserEntity(u, showInviteButton, inviteFn);
-        });
-    },
-};
+/**
+ * @param {User[]} users
+ * @param {boolean} showInviteButton
+ * @param {Function} inviteFn Called with the user ID.
+ * @return {Entity[]}
+ */
+export function fromUsers(users, showInviteButton, inviteFn) {
+    return users.map(function(u) {
+        return new UserEntity(u, showInviteButton, inviteFn);
+    });
+}
diff --git a/src/ImageUtils.js b/src/ImageUtils.js
index a83d94a633..c0f7b94b81 100644
--- a/src/ImageUtils.js
+++ b/src/ImageUtils.js
@@ -16,41 +16,38 @@ limitations under the License.
 
 'use strict';
 
-module.exports = {
-
-    /**
-     * Returns the actual height that an image of dimensions (fullWidth, fullHeight)
-     * will occupy if resized to fit inside a thumbnail bounding box of size
-     * (thumbWidth, thumbHeight).
-     *
-     * If the aspect ratio of the source image is taller than the aspect ratio of
-     * the thumbnail bounding box, then we return the thumbHeight parameter unchanged.
-     * Otherwise we return the thumbHeight parameter scaled down appropriately to
-     * reflect the actual height the scaled thumbnail occupies.
-     *
-     * This is very useful for calculating how much height a thumbnail will actually
-     * consume in the timeline, when performing scroll offset calcuations
-     * (e.g. scroll locking)
-     */
-    thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
-        if (!fullWidth || !fullHeight) {
-            // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
-            // log this because it's spammy
-            return undefined;
-        }
-        if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
-            // no scaling needs to be applied
-            return fullHeight;
-        }
-        const widthMulti = thumbWidth / fullWidth;
-        const heightMulti = thumbHeight / fullHeight;
-        if (widthMulti < heightMulti) {
-            // width is the dominant dimension so scaling will be fixed on that
-            return Math.floor(widthMulti * fullHeight);
-        } else {
-            // height is the dominant dimension so scaling will be fixed on that
-            return Math.floor(heightMulti * fullHeight);
-        }
-    },
-};
+/**
+ * Returns the actual height that an image of dimensions (fullWidth, fullHeight)
+ * will occupy if resized to fit inside a thumbnail bounding box of size
+ * (thumbWidth, thumbHeight).
+ *
+ * If the aspect ratio of the source image is taller than the aspect ratio of
+ * the thumbnail bounding box, then we return the thumbHeight parameter unchanged.
+ * Otherwise we return the thumbHeight parameter scaled down appropriately to
+ * reflect the actual height the scaled thumbnail occupies.
+ *
+ * This is very useful for calculating how much height a thumbnail will actually
+ * consume in the timeline, when performing scroll offset calcuations
+ * (e.g. scroll locking)
+ */
+export function thumbHeight(fullWidth, fullHeight, thumbWidth, thumbHeight) {
+    if (!fullWidth || !fullHeight) {
+        // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
+        // log this because it's spammy
+        return undefined;
+    }
+    if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
+        // no scaling needs to be applied
+        return fullHeight;
+    }
+    const widthMulti = thumbWidth / fullWidth;
+    const heightMulti = thumbHeight / fullHeight;
+    if (widthMulti < heightMulti) {
+        // width is the dominant dimension so scaling will be fixed on that
+        return Math.floor(widthMulti * fullHeight);
+    } else {
+        // height is the dominant dimension so scaling will be fixed on that
+        return Math.floor(heightMulti * fullHeight);
+    }
+}
 
diff --git a/src/Notifier.js b/src/Notifier.js
index dd691d8ca7..10d2048f45 100644
--- a/src/Notifier.js
+++ b/src/Notifier.js
@@ -364,4 +364,4 @@ if (!global.mxNotifier) {
     global.mxNotifier = Notifier;
 }
 
-module.exports = global.mxNotifier;
+export default global.mxNotifier;
diff --git a/src/PasswordReset.js b/src/PasswordReset.js
index 31339eb4e5..320599f6d9 100644
--- a/src/PasswordReset.js
+++ b/src/PasswordReset.js
@@ -25,7 +25,7 @@ import { _t } from './languageHandler';
  * the client owns the given email address, which is then passed to the password
  * API on the homeserver in question with the new password.
  */
-class PasswordReset {
+export default class PasswordReset {
     /**
      * Configure the endpoints for password resetting.
      * @param {string} homeserverUrl The URL to the HS which has the account to reset.
@@ -101,4 +101,3 @@ class PasswordReset {
     }
 }
 
-module.exports = PasswordReset;
diff --git a/src/PlatformPeg.js b/src/PlatformPeg.js
index 5c1112e23b..34131fde7d 100644
--- a/src/PlatformPeg.js
+++ b/src/PlatformPeg.js
@@ -47,4 +47,4 @@ class PlatformPeg {
 if (!global.mxPlatformPeg) {
     global.mxPlatformPeg = new PlatformPeg();
 }
-module.exports = global.mxPlatformPeg;
+export default global.mxPlatformPeg;
diff --git a/src/Presence.js b/src/Presence.js
index 8ef988f171..4776157514 100644
--- a/src/Presence.js
+++ b/src/Presence.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -104,4 +105,4 @@ class Presence {
     }
 }
 
-module.exports = new Presence();
+export default new Presence();
diff --git a/src/RoomListSorter.js b/src/RoomListSorter.js
index c06cc60c97..0ff37a6af2 100644
--- a/src/RoomListSorter.js
+++ b/src/RoomListSorter.js
@@ -24,12 +24,8 @@ function tsOfNewestEvent(room) {
     }
 }
 
-function mostRecentActivityFirst(roomList) {
+export function mostRecentActivityFirst(roomList) {
     return roomList.sort(function(a, b) {
         return tsOfNewestEvent(b) - tsOfNewestEvent(a);
     });
 }
-
-module.exports = {
-    mostRecentActivityFirst,
-};
diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js
index c0ffc3022d..a449c2c2b9 100644
--- a/src/ScalarMessaging.js
+++ b/src/ScalarMessaging.js
@@ -658,30 +658,29 @@ const onMessage = function(event) {
 
 let listenerCount = 0;
 let openManagerUrl = null;
-module.exports = {
-    startListening: function() {
-        if (listenerCount === 0) {
-            window.addEventListener("message", onMessage, false);
-        }
-        listenerCount += 1;
-    },
 
-    stopListening: function() {
-        listenerCount -= 1;
-        if (listenerCount === 0) {
-            window.removeEventListener("message", onMessage);
-        }
-        if (listenerCount < 0) {
-            // Make an error so we get a stack trace
-            const e = new Error(
-                "ScalarMessaging: mismatched startListening / stopListening detected." +
-                " Negative count",
-            );
-            console.error(e);
-        }
-    },
+export function startListening() {
+    if (listenerCount === 0) {
+        window.addEventListener("message", onMessage, false);
+    }
+    listenerCount += 1;
+}
 
-    setOpenManagerUrl: function(url) {
-        openManagerUrl = url;
-    },
-};
+export function stopListening() {
+    listenerCount -= 1;
+    if (listenerCount === 0) {
+        window.removeEventListener("message", onMessage);
+    }
+    if (listenerCount < 0) {
+        // Make an error so we get a stack trace
+        const e = new Error(
+            "ScalarMessaging: mismatched startListening / stopListening detected." +
+            " Negative count",
+        );
+        console.error(e);
+    }
+}
+
+export function setOpenManagerUrl(url) {
+    openManagerUrl = url;
+}
diff --git a/src/Skinner.js b/src/Skinner.js
index 7235d55937..fee234d77e 100644
--- a/src/Skinner.js
+++ b/src/Skinner.js
@@ -106,5 +106,5 @@ class Skinner {
 if (global.mxSkinner === undefined) {
     global.mxSkinner = new Skinner();
 }
-module.exports = global.mxSkinner;
+export default global.mxSkinner;
 
diff --git a/src/TextForEvent.js b/src/TextForEvent.js
index c3c8396e26..fe936d7d21 100644
--- a/src/TextForEvent.js
+++ b/src/TextForEvent.js
@@ -620,10 +620,8 @@ for (const evType of ALL_RULE_TYPES) {
     stateHandlers[evType] = textForMjolnirEvent;
 }
 
-module.exports = {
-    textForEvent: function(ev) {
-        const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
-        if (handler) return handler(ev);
-        return '';
-    },
-};
+export function textForEvent(ev) {
+    const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
+    if (handler) return handler(ev);
+    return '';
+}
diff --git a/src/Unread.js b/src/Unread.js
index d5c5993974..c2eaa468f5 100644
--- a/src/Unread.js
+++ b/src/Unread.js
@@ -18,76 +18,74 @@ const MatrixClientPeg = require('./MatrixClientPeg');
 import shouldHideEvent from './shouldHideEvent';
 const sdk = require('./index');
 
-module.exports = {
-    /**
-     * Returns true iff this event arriving in a room should affect the room's
-     * count of unread messages
-     */
-    eventTriggersUnreadCount: function(ev) {
-        if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) {
-            return false;
-        } else if (ev.getType() == 'm.room.member') {
-            return false;
-        } else if (ev.getType() == 'm.room.third_party_invite') {
-            return false;
-        } else if (ev.getType() == 'm.call.answer' || ev.getType() == 'm.call.hangup') {
-            return false;
-        } else if (ev.getType() == 'm.room.message' && ev.getContent().msgtype == 'm.notify') {
-            return false;
-        } else if (ev.getType() == 'm.room.aliases' || ev.getType() == 'm.room.canonical_alias') {
-            return false;
-        } else if (ev.getType() == 'm.room.server_acl') {
+/**
+ * Returns true iff this event arriving in a room should affect the room's
+ * count of unread messages
+ */
+export function eventTriggersUnreadCount(ev) {
+    if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) {
+        return false;
+    } else if (ev.getType() == 'm.room.member') {
+        return false;
+    } else if (ev.getType() == 'm.room.third_party_invite') {
+        return false;
+    } else if (ev.getType() == 'm.call.answer' || ev.getType() == 'm.call.hangup') {
+        return false;
+    } else if (ev.getType() == 'm.room.message' && ev.getContent().msgtype == 'm.notify') {
+        return false;
+    } else if (ev.getType() == 'm.room.aliases' || ev.getType() == 'm.room.canonical_alias') {
+        return false;
+    } else if (ev.getType() == 'm.room.server_acl') {
+        return false;
+    }
+    const EventTile = sdk.getComponent('rooms.EventTile');
+    return EventTile.haveTileForEvent(ev);
+}
+
+export function doesRoomHaveUnreadMessages(room) {
+    const myUserId = MatrixClientPeg.get().credentials.userId;
+
+    // get the most recent read receipt sent by our account.
+    // N.B. this is NOT a read marker (RM, aka "read up to marker"),
+    // despite the name of the method :((
+    const readUpToId = room.getEventReadUpTo(myUserId);
+
+    // as we don't send RRs for our own messages, make sure we special case that
+    // if *we* sent the last message into the room, we consider it not unread!
+    // Should fix: https://github.com/vector-im/riot-web/issues/3263
+    //             https://github.com/vector-im/riot-web/issues/2427
+    // ...and possibly some of the others at
+    //             https://github.com/vector-im/riot-web/issues/3363
+    if (room.timeline.length &&
+        room.timeline[room.timeline.length - 1].sender &&
+        room.timeline[room.timeline.length - 1].sender.userId === myUserId) {
+        return false;
+    }
+
+    // this just looks at whatever history we have, which if we've only just started
+    // up probably won't be very much, so if the last couple of events are ones that
+    // don't count, we don't know if there are any events that do count between where
+    // we have and the read receipt. We could fetch more history to try & find out,
+    // but currently we just guess.
+
+    // Loop through messages, starting with the most recent...
+    for (let i = room.timeline.length - 1; i >= 0; --i) {
+        const ev = room.timeline[i];
+
+        if (ev.getId() == readUpToId) {
+            // If we've read up to this event, there's nothing more recent
+            // that counts and we can stop looking because the user's read
+            // this and everything before.
             return false;
+        } else if (!shouldHideEvent(ev) && this.eventTriggersUnreadCount(ev)) {
+            // We've found a message that counts before we hit
+            // the user's read receipt, so this room is definitely unread.
+            return true;
         }
-        const EventTile = sdk.getComponent('rooms.EventTile');
-        return EventTile.haveTileForEvent(ev);
-    },
-
-    doesRoomHaveUnreadMessages: function(room) {
-        const myUserId = MatrixClientPeg.get().credentials.userId;
-
-        // get the most recent read receipt sent by our account.
-        // N.B. this is NOT a read marker (RM, aka "read up to marker"),
-        // despite the name of the method :((
-        const readUpToId = room.getEventReadUpTo(myUserId);
-
-        // as we don't send RRs for our own messages, make sure we special case that
-        // if *we* sent the last message into the room, we consider it not unread!
-        // Should fix: https://github.com/vector-im/riot-web/issues/3263
-        //             https://github.com/vector-im/riot-web/issues/2427
-        // ...and possibly some of the others at
-        //             https://github.com/vector-im/riot-web/issues/3363
-        if (room.timeline.length &&
-            room.timeline[room.timeline.length - 1].sender &&
-            room.timeline[room.timeline.length - 1].sender.userId === myUserId) {
-            return false;
-        }
-
-        // this just looks at whatever history we have, which if we've only just started
-        // up probably won't be very much, so if the last couple of events are ones that
-        // don't count, we don't know if there are any events that do count between where
-        // we have and the read receipt. We could fetch more history to try & find out,
-        // but currently we just guess.
-
-        // Loop through messages, starting with the most recent...
-        for (let i = room.timeline.length - 1; i >= 0; --i) {
-            const ev = room.timeline[i];
-
-            if (ev.getId() == readUpToId) {
-                // If we've read up to this event, there's nothing more recent
-                // that counts and we can stop looking because the user's read
-                // this and everything before.
-                return false;
-            } else if (!shouldHideEvent(ev) && this.eventTriggersUnreadCount(ev)) {
-                // We've found a message that counts before we hit
-                // the user's read receipt, so this room is definitely unread.
-                return true;
-            }
-        }
-        // If we got here, we didn't find a message that counted but didn't find
-        // the user's read receipt either, so we guess and say that the room is
-        // unread on the theory that false positives are better than false
-        // negatives here.
-        return true;
-    },
-};
+    }
+    // If we got here, we didn't find a message that counted but didn't find
+    // the user's read receipt either, so we guess and say that the room is
+    // unread on the theory that false positives are better than false
+    // negatives here.
+    return true;
+}
diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js
index eb09685cbe..d690466127 100644
--- a/src/WhoIsTyping.js
+++ b/src/WhoIsTyping.js
@@ -17,68 +17,66 @@ limitations under the License.
 import MatrixClientPeg from "./MatrixClientPeg";
 import { _t } from './languageHandler';
 
-module.exports = {
-    usersTypingApartFromMeAndIgnored: function(room) {
-        return this.usersTyping(
-            room, [MatrixClientPeg.get().credentials.userId].concat(MatrixClientPeg.get().getIgnoredUsers()),
-        );
-    },
+export function usersTypingApartFromMeAndIgnored(room) {
+    return usersTyping(
+        room, [MatrixClientPeg.get().credentials.userId].concat(MatrixClientPeg.get().getIgnoredUsers()),
+    );
+}
 
-    usersTypingApartFromMe: function(room) {
-        return this.usersTyping(
-            room, [MatrixClientPeg.get().credentials.userId],
-        );
-    },
+export function usersTypingApartFromMe(room) {
+    return usersTyping(
+        room, [MatrixClientPeg.get().credentials.userId],
+    );
+}
 
-    /**
-     * Given a Room object and, optionally, a list of userID strings
-     * to exclude, return a list of user objects who are typing.
-     * @param {Room} room: room object to get users from.
-     * @param {string[]} exclude: list of user mxids to exclude.
-     * @returns {string[]} list of user objects who are typing.
-     */
-    usersTyping: function(room, exclude) {
-        const whoIsTyping = [];
+/**
+ * Given a Room object and, optionally, a list of userID strings
+ * to exclude, return a list of user objects who are typing.
+ * @param {Room} room: room object to get users from.
+ * @param {string[]} exclude: list of user mxids to exclude.
+ * @returns {string[]} list of user objects who are typing.
+ */
+export function usersTyping(room, exclude) {
+    const whoIsTyping = [];
 
-        if (exclude === undefined) {
-            exclude = [];
-        }
+    if (exclude === undefined) {
+        exclude = [];
+    }
 
-        const memberKeys = Object.keys(room.currentState.members);
-        for (let i = 0; i < memberKeys.length; ++i) {
-            const userId = memberKeys[i];
+    const memberKeys = Object.keys(room.currentState.members);
+    for (let i = 0; i < memberKeys.length; ++i) {
+        const userId = memberKeys[i];
 
-            if (room.currentState.members[userId].typing) {
-                if (exclude.indexOf(userId) === -1) {
-                    whoIsTyping.push(room.currentState.members[userId]);
-                }
+        if (room.currentState.members[userId].typing) {
+            if (exclude.indexOf(userId) === -1) {
+                whoIsTyping.push(room.currentState.members[userId]);
             }
         }
+    }
 
-        return whoIsTyping;
-    },
+    return whoIsTyping;
+}
 
-    whoIsTypingString: function(whoIsTyping, limit) {
-        let othersCount = 0;
-        if (whoIsTyping.length > limit) {
-            othersCount = whoIsTyping.length - limit + 1;
-        }
-        if (whoIsTyping.length === 0) {
-            return '';
-        } else if (whoIsTyping.length === 1) {
-            return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name});
-        }
-        const names = whoIsTyping.map(function(m) {
-            return m.name;
+export function whoIsTypingString(whoIsTyping, limit) {
+    let othersCount = 0;
+    if (whoIsTyping.length > limit) {
+        othersCount = whoIsTyping.length - limit + 1;
+    }
+    if (whoIsTyping.length === 0) {
+        return '';
+    } else if (whoIsTyping.length === 1) {
+        return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name});
+    }
+    const names = whoIsTyping.map(function(m) {
+        return m.name;
+    });
+    if (othersCount>=1) {
+        return _t('%(names)s and %(count)s others are typing …', {
+            names: names.slice(0, limit - 1).join(', '),
+            count: othersCount,
         });
-        if (othersCount>=1) {
-            return _t('%(names)s and %(count)s others are typing …', {
-                names: names.slice(0, limit - 1).join(', '),
-                count: othersCount,
-            });
-        } else {
-            const lastPerson = names.pop();
-            return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson});
-        }
-    },
-};
+    } else {
+        const lastPerson = names.pop();
+        return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson});
+    }
+}
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index 145203136a..b6383c9dab 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -21,7 +21,7 @@ import { _t } from '../../../languageHandler';
 const sdk = require('../../../index');
 const MatrixClientPeg = require("../../../MatrixClientPeg");
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'EncryptedEventDialog',
 
     propTypes: {
diff --git a/src/components/structures/CompatibilityPage.js b/src/components/structures/CompatibilityPage.js
index 28c86f8dd8..9a3fdb5f39 100644
--- a/src/components/structures/CompatibilityPage.js
+++ b/src/components/structures/CompatibilityPage.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -20,7 +21,7 @@ import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CompatibilityPage',
     propTypes: {
         onAccept: PropTypes.func,
diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js
index f5a5912dd5..b6fbf6d45d 100644
--- a/src/components/structures/FilePanel.js
+++ b/src/components/structures/FilePanel.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -126,4 +127,4 @@ const FilePanel = createReactClass({
     },
 });
 
-module.exports = FilePanel;
+export default FilePanel;
diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js
index a0ad2b5c81..57cbd6ec59 100644
--- a/src/components/structures/LeftPanel.js
+++ b/src/components/structures/LeftPanel.js
@@ -308,4 +308,4 @@ const LeftPanel = createReactClass({
     },
 });
 
-module.exports = LeftPanel;
+export default LeftPanel;
diff --git a/src/components/structures/NotificationPanel.js b/src/components/structures/NotificationPanel.js
index 470c7c8728..b65365b7e4 100644
--- a/src/components/structures/NotificationPanel.js
+++ b/src/components/structures/NotificationPanel.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2016 OpenMarket Ltd
 Copyright 2019 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -60,4 +61,4 @@ const NotificationPanel = createReactClass({
     },
 });
 
-module.exports = NotificationPanel;
+export default NotificationPanel;
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index 4823b0976c..16333d51c0 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -38,7 +38,7 @@ function track(action) {
     Analytics.trackEvent('RoomDirectory', action);
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomDirectory',
 
     propTypes: {
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index b0aa4cb59b..e7a0771962 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2017, 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -38,7 +39,7 @@ function getUnsentMessages(room) {
     });
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomStatusBar',
 
     propTypes: {
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 2f8d274866..3f9d680503 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -72,7 +72,7 @@ const RoomContext = PropTypes.shape({
     room: PropTypes.instanceOf(Room),
 });
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomView',
     propTypes: {
         ConferenceHandler: PropTypes.any,
diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js
index 17583a22ed..c5725e1343 100644
--- a/src/components/structures/ScrollPanel.js
+++ b/src/components/structures/ScrollPanel.js
@@ -84,7 +84,7 @@ if (DEBUG_SCROLL) {
  * offset as normal.
  */
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ScrollPanel',
 
     propTypes: {
diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js
index 0aa2e15f4c..faa20a68ba 100644
--- a/src/components/structures/SearchBox.js
+++ b/src/components/structures/SearchBox.js
@@ -24,7 +24,7 @@ import { throttle } from 'lodash';
 import AccessibleButton from '../../components/views/elements/AccessibleButton';
 import classNames from 'classnames';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'SearchBox',
 
     propTypes: {
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 41283b5308..d0f99aec91 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -1347,4 +1347,4 @@ const TimelinePanel = createReactClass({
     },
 });
 
-module.exports = TimelinePanel;
+export default TimelinePanel;
diff --git a/src/components/structures/UploadBar.js b/src/components/structures/UploadBar.js
index da0ca7fe99..ce5441089c 100644
--- a/src/components/structures/UploadBar.js
+++ b/src/components/structures/UploadBar.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ const dis = require('../../dispatcher');
 const filesize = require('filesize');
 import { _t } from '../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'UploadBar',
     propTypes: {
         room: PropTypes.object,
diff --git a/src/components/structures/ViewSource.js b/src/components/structures/ViewSource.js
index ef4ede517a..e946b5afbf 100644
--- a/src/components/structures/ViewSource.js
+++ b/src/components/structures/ViewSource.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ import {_t} from "../../languageHandler";
 import sdk from "../../index";
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ViewSource',
 
     propTypes: {
diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js
index ada7d4449b..6a84913f36 100644
--- a/src/components/structures/auth/ForgotPassword.js
+++ b/src/components/structures/auth/ForgotPassword.js
@@ -40,7 +40,7 @@ const PHASE_EMAIL_SENT = 3;
 // User has clicked the link in email and completed reset
 const PHASE_DONE = 4;
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ForgotPassword',
 
     propTypes: {
diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js
index ade417d156..dc2755be8e 100644
--- a/src/components/structures/auth/Login.js
+++ b/src/components/structures/auth/Login.js
@@ -54,7 +54,7 @@ _td("General failure");
 /**
  * A wire component which glues together login UI components and Login logic
  */
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'Login',
 
     propTypes: {
diff --git a/src/components/structures/auth/PostRegistration.js b/src/components/structures/auth/PostRegistration.js
index a77b4d0d56..128c061cc4 100644
--- a/src/components/structures/auth/PostRegistration.js
+++ b/src/components/structures/auth/PostRegistration.js
@@ -22,7 +22,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import AuthPage from "../../views/auth/AuthPage";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PostRegistration',
 
     propTypes: {
diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js
index 69f34f764a..fce77631f8 100644
--- a/src/components/structures/auth/Registration.js
+++ b/src/components/structures/auth/Registration.js
@@ -41,7 +41,7 @@ const PHASE_REGISTRATION = 1;
 // Enable phases for registration
 const PHASES_ENABLED = true;
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'Registration',
 
     propTypes: {
diff --git a/src/components/views/auth/AuthFooter.js b/src/components/views/auth/AuthFooter.js
index 39d636f9cc..4076141606 100644
--- a/src/components/views/auth/AuthFooter.js
+++ b/src/components/views/auth/AuthFooter.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2019 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,7 @@ import { _t } from '../../../languageHandler';
 import React from 'react';
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'AuthFooter',
 
     render: function() {
diff --git a/src/components/views/auth/AuthHeader.js b/src/components/views/auth/AuthHeader.js
index 193f347857..7048472681 100644
--- a/src/components/views/auth/AuthHeader.js
+++ b/src/components/views/auth/AuthHeader.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import sdk from '../../../index';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'AuthHeader',
 
     render: function() {
diff --git a/src/components/views/auth/CaptchaForm.js b/src/components/views/auth/CaptchaForm.js
index f907a58026..2da837f029 100644
--- a/src/components/views/auth/CaptchaForm.js
+++ b/src/components/views/auth/CaptchaForm.js
@@ -24,7 +24,7 @@ const DIV_ID = 'mx_recaptcha';
 /**
  * A pure UI component which displays a captcha form.
  */
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CaptchaForm',
 
     propTypes: {
diff --git a/src/components/views/auth/CustomServerDialog.js b/src/components/views/auth/CustomServerDialog.js
index a9a3a53f02..024951e6c0 100644
--- a/src/components/views/auth/CustomServerDialog.js
+++ b/src/components/views/auth/CustomServerDialog.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CustomServerDialog',
 
     render: function() {
diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js
index 03fb74462c..28efe60d0e 100644
--- a/src/components/views/auth/RegistrationForm.js
+++ b/src/components/views/auth/RegistrationForm.js
@@ -41,7 +41,7 @@ const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from of
 /**
  * A pure UI component which displays a registration form.
  */
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RegistrationForm',
 
     propTypes: {
diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js
index 82db78615e..ae9eaba488 100644
--- a/src/components/views/avatars/BaseAvatar.js
+++ b/src/components/views/avatars/BaseAvatar.js
@@ -2,6 +2,7 @@
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2018 New Vector Ltd
 Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -24,7 +25,7 @@ import AvatarLogic from '../../../Avatar';
 import SettingsStore from "../../../settings/SettingsStore";
 import AccessibleButton from '../elements/AccessibleButton';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'BaseAvatar',
 
     propTypes: {
diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js
index 383bab5e79..4f84191ccd 100644
--- a/src/components/views/avatars/MemberAvatar.js
+++ b/src/components/views/avatars/MemberAvatar.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ const Avatar = require('../../../Avatar');
 const sdk = require("../../../index");
 const dispatcher = require("../../../dispatcher");
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MemberAvatar',
 
     propTypes: {
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index 6f8f236afc..3e02e439ff 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -22,7 +22,7 @@ import Modal from '../../../Modal';
 import sdk from "../../../index";
 import Avatar from '../../../Avatar';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomAvatar',
 
     // Room may be left unset here, but if it is,
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index efbfc4322f..1011b6ce46 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -37,7 +37,7 @@ function canCancel(eventStatus) {
     return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MessageContextMenu',
 
     propTypes: {
diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js
index f5e68bd20b..902506b015 100644
--- a/src/components/views/context_menus/RoomTileContextMenu.js
+++ b/src/components/views/context_menus/RoomTileContextMenu.js
@@ -63,7 +63,7 @@ const NotifOption = ({active, onClick, src, label}) => {
     );
 };
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomTileContextMenu',
 
     propTypes: {
diff --git a/src/components/views/create_room/CreateRoomButton.js b/src/components/views/create_room/CreateRoomButton.js
index 1c44aed78c..adf3972eff 100644
--- a/src/components/views/create_room/CreateRoomButton.js
+++ b/src/components/views/create_room/CreateRoomButton.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CreateRoomButton',
     propTypes: {
         onCreateRoom: PropTypes.func,
diff --git a/src/components/views/create_room/Presets.js b/src/components/views/create_room/Presets.js
index f512c3e2fd..0f18d11511 100644
--- a/src/components/views/create_room/Presets.js
+++ b/src/components/views/create_room/Presets.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -25,7 +26,7 @@ const Presets = {
     Custom: "custom",
 };
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CreateRoomPresets',
     propTypes: {
         onChange: PropTypes.func,
diff --git a/src/components/views/create_room/RoomAlias.js b/src/components/views/create_room/RoomAlias.js
index fd3e3365f7..bc5dec1468 100644
--- a/src/components/views/create_room/RoomAlias.js
+++ b/src/components/views/create_room/RoomAlias.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomAlias',
     propTypes: {
         // Specifying a homeserver will make magical things happen when you,
diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js
index 2be505a798..b7d8f3f55f 100644
--- a/src/components/views/dialogs/AddressPickerDialog.js
+++ b/src/components/views/dialogs/AddressPickerDialog.js
@@ -43,7 +43,7 @@ const addressTypeName = {
 };
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: "AddressPickerDialog",
 
     propTypes: {
diff --git a/src/components/views/elements/DialogButtons.js b/src/components/views/elements/DialogButtons.js
index e7b3a9c7eb..4e47e73052 100644
--- a/src/components/views/elements/DialogButtons.js
+++ b/src/components/views/elements/DialogButtons.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2017 Aidan Gauland
 Copyright 2018 New Vector Ltd.
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ import { _t } from '../../../languageHandler';
 /**
  * Basic container for buttons in modal dialogs.
  */
-module.exports = createReactClass({
+export default createReactClass({
     displayName: "DialogButtons",
 
     propTypes: {
diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js
index 5913682255..fbac63cbba 100644
--- a/src/components/views/elements/EditableText.js
+++ b/src/components/views/elements/EditableText.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {Key} from "../../../Keyboard";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'EditableText',
 
     propTypes: {
diff --git a/src/components/views/elements/InlineSpinner.js b/src/components/views/elements/InlineSpinner.js
index 18711f90d3..ad70471d89 100644
--- a/src/components/views/elements/InlineSpinner.js
+++ b/src/components/views/elements/InlineSpinner.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from "react";
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'InlineSpinner',
 
     render: function() {
diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js
index ef80efaa68..4db0ad1c68 100644
--- a/src/components/views/elements/MemberEventListSummary.js
+++ b/src/components/views/elements/MemberEventListSummary.js
@@ -24,7 +24,7 @@ import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
 import sdk from "../../../index";
 import {MatrixEvent} from "matrix-js-sdk";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MemberEventListSummary',
 
     propTypes: {
diff --git a/src/components/views/elements/MessageSpinner.js b/src/components/views/elements/MessageSpinner.js
index f00fdcf576..1775fdd4d7 100644
--- a/src/components/views/elements/MessageSpinner.js
+++ b/src/components/views/elements/MessageSpinner.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MessageSpinner',
 
     render: function() {
diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js
index 19e4be6083..996dbf2283 100644
--- a/src/components/views/elements/PersistentApp.js
+++ b/src/components/views/elements/PersistentApp.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ import WidgetUtils from '../../../utils/WidgetUtils';
 import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PersistentApp',
 
     getInitialState: function() {
diff --git a/src/components/views/elements/PowerSelector.js b/src/components/views/elements/PowerSelector.js
index e6babded32..2f4c08922a 100644
--- a/src/components/views/elements/PowerSelector.js
+++ b/src/components/views/elements/PowerSelector.js
@@ -22,7 +22,7 @@ import { _t } from '../../../languageHandler';
 import Field from "./Field";
 import {Key} from "../../../Keyboard";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PowerSelector',
 
     propTypes: {
diff --git a/src/components/views/elements/ProgressBar.js b/src/components/views/elements/ProgressBar.js
index 3561763e51..045731ba38 100644
--- a/src/components/views/elements/ProgressBar.js
+++ b/src/components/views/elements/ProgressBar.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -18,7 +19,7 @@ import React from "react";
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ProgressBar',
     propTypes: {
         value: PropTypes.number,
diff --git a/src/components/views/elements/SettingsFlag.js b/src/components/views/elements/SettingsFlag.js
index a3a6d18d33..15f17805a8 100644
--- a/src/components/views/elements/SettingsFlag.js
+++ b/src/components/views/elements/SettingsFlag.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017 Travis Ralston
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ import SettingsStore from "../../../settings/SettingsStore";
 import { _t } from '../../../languageHandler';
 import ToggleSwitch from "./ToggleSwitch";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'SettingsFlag',
     propTypes: {
         name: PropTypes.string.isRequired,
diff --git a/src/components/views/elements/Spinner.js b/src/components/views/elements/Spinner.js
index 5d43e836cc..b1fe97d5d2 100644
--- a/src/components/views/elements/Spinner.js
+++ b/src/components/views/elements/Spinner.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -17,7 +18,7 @@ limitations under the License.
 import React from "react";
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'Spinner',
 
     render: function() {
diff --git a/src/components/views/elements/TintableSvg.js b/src/components/views/elements/TintableSvg.js
index 73ba375d59..3e0e41f411 100644
--- a/src/components/views/elements/TintableSvg.js
+++ b/src/components/views/elements/TintableSvg.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -83,4 +84,4 @@ Tinter.registerTintable(function() {
     }
 });
 
-module.exports = TintableSvg;
+export default TintableSvg;
diff --git a/src/components/views/elements/Tooltip.js b/src/components/views/elements/Tooltip.js
index 8ff3ce9bdb..fd845d9db3 100644
--- a/src/components/views/elements/Tooltip.js
+++ b/src/components/views/elements/Tooltip.js
@@ -2,6 +2,7 @@
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2019 New Vector Ltd
 Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -26,7 +27,7 @@ import classNames from 'classnames';
 
 const MIN_TOOLTIP_HEIGHT = 25;
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'Tooltip',
 
     propTypes: {
diff --git a/src/components/views/elements/TooltipButton.js b/src/components/views/elements/TooltipButton.js
index 0cabf776a4..29a18d4b34 100644
--- a/src/components/views/elements/TooltipButton.js
+++ b/src/components/views/elements/TooltipButton.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import sdk from '../../../index';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'TooltipButton',
 
     getInitialState: function() {
diff --git a/src/components/views/elements/TruncatedList.js b/src/components/views/elements/TruncatedList.js
index e6a5e2ae32..9ce2395638 100644
--- a/src/components/views/elements/TruncatedList.js
+++ b/src/components/views/elements/TruncatedList.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'TruncatedList',
 
     propTypes: {
diff --git a/src/components/views/elements/UserSelector.js b/src/components/views/elements/UserSelector.js
index 1010d4144c..706c6ed2e5 100644
--- a/src/components/views/elements/UserSelector.js
+++ b/src/components/views/elements/UserSelector.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'UserSelector',
 
     propTypes: {
diff --git a/src/components/views/globals/MatrixToolbar.js b/src/components/views/globals/MatrixToolbar.js
index aabf0810f8..ac449c39d7 100644
--- a/src/components/views/globals/MatrixToolbar.js
+++ b/src/components/views/globals/MatrixToolbar.js
@@ -20,7 +20,7 @@ import { _t } from '../../../languageHandler';
 import Notifier from '../../../Notifier';
 import AccessibleButton from '../../../components/views/elements/AccessibleButton';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MatrixToolbar',
 
     hideToolbar: function() {
diff --git a/src/components/views/groups/GroupMemberInfo.js b/src/components/views/groups/GroupMemberInfo.js
index 3dac90fc35..e028f5a000 100644
--- a/src/components/views/groups/GroupMemberInfo.js
+++ b/src/components/views/groups/GroupMemberInfo.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2017 Vector Creations Ltd
 Copyright 2017 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -27,7 +28,7 @@ import { GroupMemberType } from '../../../groups';
 import GroupStore from '../../../stores/GroupStore';
 import AccessibleButton from '../elements/AccessibleButton';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'GroupMemberInfo',
 
     contextTypes: {
diff --git a/src/components/views/groups/GroupRoomInfo.js b/src/components/views/groups/GroupRoomInfo.js
index f9f7324e23..1460c7bf0b 100644
--- a/src/components/views/groups/GroupRoomInfo.js
+++ b/src/components/views/groups/GroupRoomInfo.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -24,7 +25,7 @@ import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import GroupStore from '../../../stores/GroupStore';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'GroupRoomInfo',
 
     contextTypes: {
diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js
index 552b1108d2..37f1401a58 100644
--- a/src/components/views/messages/MFileBody.js
+++ b/src/components/views/messages/MFileBody.js
@@ -194,7 +194,7 @@ function computedStyle(element) {
     return cssText;
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MFileBody',
 
     getInitialState: function() {
diff --git a/src/components/views/messages/MVideoBody.js b/src/components/views/messages/MVideoBody.js
index 8366d0dd01..7d0c782bdc 100644
--- a/src/components/views/messages/MVideoBody.js
+++ b/src/components/views/messages/MVideoBody.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ import { decryptFile } from '../../../utils/DecryptFile';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MVideoBody',
 
     propTypes: {
diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js
index ba271f95b5..61170111c7 100644
--- a/src/components/views/messages/MessageEvent.js
+++ b/src/components/views/messages/MessageEvent.js
@@ -21,7 +21,7 @@ import sdk from '../../../index';
 import SettingsStore from "../../../settings/SettingsStore";
 import {Mjolnir} from "../../../mjolnir/Mjolnir";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MessageEvent',
 
     propTypes: {
diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js
index 513e104d12..faae53776d 100644
--- a/src/components/views/messages/RoomAvatarEvent.js
+++ b/src/components/views/messages/RoomAvatarEvent.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2017 Vector Creations Ltd
 Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -24,7 +25,7 @@ import sdk from '../../../index';
 import Modal from '../../../Modal';
 import AccessibleButton from '../elements/AccessibleButton';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomAvatarEvent',
 
     propTypes: {
diff --git a/src/components/views/messages/RoomCreate.js b/src/components/views/messages/RoomCreate.js
index 9bb6fcc0d8..8689a636d8 100644
--- a/src/components/views/messages/RoomCreate.js
+++ b/src/components/views/messages/RoomCreate.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomCreate',
 
     propTypes: {
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 6bf45d9193..48144fbb2d 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -35,7 +35,7 @@ import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
 import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
 import {toRightOf} from "../../structures/ContextMenu";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'TextualBody',
 
     propTypes: {
diff --git a/src/components/views/messages/TextualEvent.js b/src/components/views/messages/TextualEvent.js
index be9adeed77..83b3c84f1e 100644
--- a/src/components/views/messages/TextualEvent.js
+++ b/src/components/views/messages/TextualEvent.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -20,7 +21,7 @@ import createReactClass from 'create-react-class';
 
 const TextForEvent = require('../../../TextForEvent');
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'TextualEvent',
 
     propTypes: {
diff --git a/src/components/views/messages/UnknownBody.js b/src/components/views/messages/UnknownBody.js
index ed2306de4f..2a19f324e8 100644
--- a/src/components/views/messages/UnknownBody.js
+++ b/src/components/views/messages/UnknownBody.js
@@ -18,7 +18,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'UnknownBody',
 
     render: function() {
diff --git a/src/components/views/room_settings/ColorSettings.js b/src/components/views/room_settings/ColorSettings.js
index 952c49828b..1e06da0cd8 100644
--- a/src/components/views/room_settings/ColorSettings.js
+++ b/src/components/views/room_settings/ColorSettings.js
@@ -40,7 +40,7 @@ const ROOM_COLORS = [
 // has a high possibility of being used in the nearish future.
 // Ref: https://github.com/vector-im/riot-web/issues/8421
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ColorSettings',
 
     propTypes: {
diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js
index 7a8332cc9f..30420b193f 100644
--- a/src/components/views/room_settings/UrlPreviewSettings.js
+++ b/src/components/views/room_settings/UrlPreviewSettings.js
@@ -1,7 +1,8 @@
 /*
 Copyright 2016 OpenMarket Ltd
 Copyright 2017 Travis Ralston
-Copyright 2018-2019 New Vector Ltd
+Copyright 2018, 2019 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -26,7 +27,7 @@ import dis from "../../../dispatcher";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'UrlPreviewSettings',
 
     propTypes: {
diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js
index e53570dc5b..5cf7923df3 100644
--- a/src/components/views/rooms/AppsDrawer.js
+++ b/src/components/views/rooms/AppsDrawer.js
@@ -34,7 +34,7 @@ import SettingsStore from "../../../settings/SettingsStore";
 // The maximum number of widgets that can be added in a room
 const MAX_WIDGETS = 2;
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'AppsDrawer',
 
     propTypes: {
diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js
index a83160ddbf..498a7131a2 100644
--- a/src/components/views/rooms/AuxPanel.js
+++ b/src/components/views/rooms/AuxPanel.js
@@ -29,7 +29,7 @@ import RateLimitedFunc from '../../../ratelimitedfunc';
 import SettingsStore from "../../../settings/SettingsStore";
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'AuxPanel',
 
     propTypes: {
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 988482df7f..8f645522a3 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -118,7 +118,7 @@ const MAX_READ_AVATARS = 5;
 // |    '--------------------------------------'              |
 // '----------------------------------------------------------'
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'EventTile',
 
     propTypes: {
diff --git a/src/components/views/rooms/ForwardMessage.js b/src/components/views/rooms/ForwardMessage.js
index 4a6c560d2c..7e48071fe5 100644
--- a/src/components/views/rooms/ForwardMessage.js
+++ b/src/components/views/rooms/ForwardMessage.js
@@ -23,7 +23,7 @@ import dis from '../../../dispatcher';
 import { KeyCode } from '../../../Keyboard';
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ForwardMessage',
 
     propTypes: {
diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js
index 2e3a3915d0..985ddc43bd 100644
--- a/src/components/views/rooms/LinkPreviewWidget.js
+++ b/src/components/views/rooms/LinkPreviewWidget.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -25,7 +26,7 @@ const MatrixClientPeg = require('../../../MatrixClientPeg');
 const ImageUtils = require('../../../ImageUtils');
 const Modal = require('../../../Modal');
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'LinkPreviewWidget',
 
     propTypes: {
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index 1a2c8e2212..d6e23bd87c 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -50,7 +50,7 @@ import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import {EventTimeline} from "matrix-js-sdk";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MemberInfo',
 
     propTypes: {
diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js
index 05464b43c9..a74d34c02c 100644
--- a/src/components/views/rooms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -32,7 +32,7 @@ const INITIAL_LOAD_NUM_MEMBERS = 30;
 const INITIAL_LOAD_NUM_INVITED = 5;
 const SHOW_MORE_INCREMENT = 100;
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MemberList',
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js
index c002849450..eacb35c69d 100644
--- a/src/components/views/rooms/MemberTile.js
+++ b/src/components/views/rooms/MemberTile.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -24,7 +25,7 @@ const sdk = require('../../../index');
 const dis = require('../../../dispatcher');
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'MemberTile',
 
     propTypes: {
diff --git a/src/components/views/rooms/PinnedEventTile.js b/src/components/views/rooms/PinnedEventTile.js
index 1279c01049..ca03fd787c 100644
--- a/src/components/views/rooms/PinnedEventTile.js
+++ b/src/components/views/rooms/PinnedEventTile.js
@@ -25,7 +25,7 @@ import MemberAvatar from "../avatars/MemberAvatar";
 import { _t } from '../../../languageHandler';
 import {formatFullDate} from '../../../DateUtils';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PinnedEventTile',
     propTypes: {
         mxRoom: PropTypes.object.isRequired,
diff --git a/src/components/views/rooms/PinnedEventsPanel.js b/src/components/views/rooms/PinnedEventsPanel.js
index dd2febdf39..3f07e25588 100644
--- a/src/components/views/rooms/PinnedEventsPanel.js
+++ b/src/components/views/rooms/PinnedEventsPanel.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017 Travis Ralston
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ import PinnedEventTile from "./PinnedEventTile";
 import { _t } from '../../../languageHandler';
 import PinningUtils from "../../../utils/PinningUtils";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PinnedEventsPanel',
     propTypes: {
         // The Room from the js-sdk we're going to show pinned events for
diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js
index 5cb34b473f..f9dcd7e89d 100644
--- a/src/components/views/rooms/PresenceLabel.js
+++ b/src/components/views/rooms/PresenceLabel.js
@@ -21,7 +21,7 @@ import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'PresenceLabel',
 
     propTypes: {
diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js
index 27c5e8c20e..7dda4651b5 100644
--- a/src/components/views/rooms/ReadReceiptMarker.js
+++ b/src/components/views/rooms/ReadReceiptMarker.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -35,7 +36,7 @@ try {
 } catch (e) {
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ReadReceiptMarker',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomDropTarget.js b/src/components/views/rooms/RoomDropTarget.js
index 1012b23105..61b7ca6d59 100644
--- a/src/components/views/rooms/RoomDropTarget.js
+++ b/src/components/views/rooms/RoomDropTarget.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -17,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomDropTarget',
 
     render: function() {
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index eaf2e733ca..8567c32563 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -32,7 +33,7 @@ import SettingsStore from "../../../settings/SettingsStore";
 import RoomHeaderButtons from '../right_panel/RoomHeaderButtons';
 import E2EIcon from './E2EIcon';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomHeader',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 210c9394dc..496f942245 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -49,7 +49,7 @@ function labelForTagName(tagName) {
     return tagName;
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomList',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js
index 375a4b42b1..d227574ed1 100644
--- a/src/components/views/rooms/RoomNameEditor.js
+++ b/src/components/views/rooms/RoomNameEditor.js
@@ -21,7 +21,7 @@ const sdk = require('../../../index');
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomNameEditor',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js
index a43a4df158..e460c2583f 100644
--- a/src/components/views/rooms/RoomPreviewBar.js
+++ b/src/components/views/rooms/RoomPreviewBar.js
@@ -43,7 +43,7 @@ const MessageCase = Object.freeze({
     OtherError: "OtherError",
 });
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomPreviewBar',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 817ada9706..1ae0af29c2 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -33,7 +33,7 @@ import RoomViewStore from '../../../stores/RoomViewStore';
 import SettingsStore from "../../../settings/SettingsStore";
 import {_t} from "../../../languageHandler";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomTile',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomTopicEditor.js b/src/components/views/rooms/RoomTopicEditor.js
index a7d11313ff..2a58dcef39 100644
--- a/src/components/views/rooms/RoomTopicEditor.js
+++ b/src/components/views/rooms/RoomTopicEditor.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import sdk from '../../../index';
 import { _t } from "../../../languageHandler";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomTopicEditor',
 
     propTypes: {
diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.js b/src/components/views/rooms/RoomUpgradeWarningBar.js
index 58d959ddcc..f1117ff8c6 100644
--- a/src/components/views/rooms/RoomUpgradeWarningBar.js
+++ b/src/components/views/rooms/RoomUpgradeWarningBar.js
@@ -23,7 +23,7 @@ import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'RoomUpgradeWarningBar',
 
     propTypes: {
diff --git a/src/components/views/rooms/SearchBar.js b/src/components/views/rooms/SearchBar.js
index 492c29a621..4edcab3d16 100644
--- a/src/components/views/rooms/SearchBar.js
+++ b/src/components/views/rooms/SearchBar.js
@@ -20,7 +20,7 @@ const classNames = require('classnames');
 const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'SearchBar',
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js
index 19ed490683..f5e77879b2 100644
--- a/src/components/views/rooms/SearchResultTile.js
+++ b/src/components/views/rooms/SearchResultTile.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import sdk from '../../../index';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'SearchResult',
 
     propTypes: {
diff --git a/src/components/views/rooms/SearchableEntityList.js b/src/components/views/rooms/SearchableEntityList.js
index 024816c6fc..bbc98cedef 100644
--- a/src/components/views/rooms/SearchableEntityList.js
+++ b/src/components/views/rooms/SearchableEntityList.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -182,4 +183,4 @@ const SearchableEntityList = createReactClass({
     },
 });
 
- module.exports = SearchableEntityList;
+export default SearchableEntityList;
diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js
index c7a1a22580..04805c799f 100644
--- a/src/components/views/rooms/TopUnreadMessagesBar.js
+++ b/src/components/views/rooms/TopUnreadMessagesBar.js
@@ -22,7 +22,7 @@ import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 import AccessibleButton from '../elements/AccessibleButton';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'TopUnreadMessagesBar',
 
     propTypes: {
diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js
index 76afda6dd7..0234d1ed85 100644
--- a/src/components/views/rooms/UserTile.js
+++ b/src/components/views/rooms/UserTile.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ import createReactClass from 'create-react-class';
 const Avatar = require("../../../Avatar");
 const sdk = require('../../../index');
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'UserTile',
 
     propTypes: {
diff --git a/src/components/views/rooms/WhoIsTypingTile.js b/src/components/views/rooms/WhoIsTypingTile.js
index 0e23286eb6..567d821a5e 100644
--- a/src/components/views/rooms/WhoIsTypingTile.js
+++ b/src/components/views/rooms/WhoIsTypingTile.js
@@ -23,7 +23,7 @@ import Timer from '../../../utils/Timer';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import MemberAvatar from '../avatars/MemberAvatar';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'WhoIsTypingTile',
 
     propTypes: {
diff --git a/src/components/views/settings/ChangeAvatar.js b/src/components/views/settings/ChangeAvatar.js
index 904b17b15f..3718e8d2db 100644
--- a/src/components/views/settings/ChangeAvatar.js
+++ b/src/components/views/settings/ChangeAvatar.js
@@ -21,7 +21,7 @@ import MatrixClientPeg from "../../../MatrixClientPeg";
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ChangeAvatar',
     propTypes: {
         initialAvatarUrl: PropTypes.string,
diff --git a/src/components/views/settings/ChangeDisplayName.js b/src/components/views/settings/ChangeDisplayName.js
index 90c761ba3d..65aa8a9af6 100644
--- a/src/components/views/settings/ChangeDisplayName.js
+++ b/src/components/views/settings/ChangeDisplayName.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ChangeDisplayName',
 
     _getDisplayName: async function() {
diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js
index a317c46cec..db38fa065a 100644
--- a/src/components/views/settings/ChangePassword.js
+++ b/src/components/views/settings/ChangePassword.js
@@ -30,7 +30,7 @@ import { _t } from '../../../languageHandler';
 
 import sessionStore from '../../../stores/SessionStore';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'ChangePassword',
 
     propTypes: {
diff --git a/src/components/views/settings/EnableNotificationsButton.js b/src/components/views/settings/EnableNotificationsButton.js
index 1f65c39e6e..9ca591f30e 100644
--- a/src/components/views/settings/EnableNotificationsButton.js
+++ b/src/components/views/settings/EnableNotificationsButton.js
@@ -20,7 +20,7 @@ import Notifier from "../../../Notifier";
 import dis from "../../../dispatcher";
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'EnableNotificationsButton',
 
     componentDidMount: function() {
diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js
index 7345980bff..cc0841011f 100644
--- a/src/components/views/settings/Notifications.js
+++ b/src/components/views/settings/Notifications.js
@@ -63,7 +63,7 @@ function portLegacyActions(actions) {
     }
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'Notifications',
 
     phases: {
diff --git a/src/components/views/voip/CallPreview.js b/src/components/views/voip/CallPreview.js
index 15c30dcb5b..d049e23dcf 100644
--- a/src/components/views/voip/CallPreview.js
+++ b/src/components/views/voip/CallPreview.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017, 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ import CallHandler from '../../../CallHandler';
 import dis from '../../../dispatcher';
 import sdk from '../../../index';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CallPreview',
 
     propTypes: {
diff --git a/src/components/views/voip/CallView.js b/src/components/views/voip/CallView.js
index 3a62ffbac2..79c1c13c30 100644
--- a/src/components/views/voip/CallView.js
+++ b/src/components/views/voip/CallView.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'CallView',
 
     propTypes: {
diff --git a/src/components/views/voip/IncomingCallBox.js b/src/components/views/voip/IncomingCallBox.js
index 2a2839d103..7317e0a63f 100644
--- a/src/components/views/voip/IncomingCallBox.js
+++ b/src/components/views/voip/IncomingCallBox.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import sdk from '../../../index';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'IncomingCallBox',
 
     propTypes: {
diff --git a/src/components/views/voip/VideoFeed.js b/src/components/views/voip/VideoFeed.js
index 0faa227088..4210c60177 100644
--- a/src/components/views/voip/VideoFeed.js
+++ b/src/components/views/voip/VideoFeed.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -18,7 +19,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'VideoFeed',
 
     propTypes: {
diff --git a/src/components/views/voip/VideoView.js b/src/components/views/voip/VideoView.js
index 83584bcc68..4409e1aad5 100644
--- a/src/components/views/voip/VideoView.js
+++ b/src/components/views/voip/VideoView.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -34,7 +35,7 @@ function getFullScreenElement() {
     );
 }
 
-module.exports = createReactClass({
+export default createReactClass({
     displayName: 'VideoView',
 
     propTypes: {
diff --git a/src/createRoom.js b/src/createRoom.js
index 0ee90beba8..d47343abf6 100644
--- a/src/createRoom.js
+++ b/src/createRoom.js
@@ -35,7 +35,7 @@ import {getAddressType} from "./UserAddress";
  * @returns {Promise} which resolves to the room id, or null if the
  * action was aborted or failed.
  */
-function createRoom(opts) {
+export default function createRoom(opts) {
     opts = opts || {};
     if (opts.spinner === undefined) opts.spinner = true;
 
@@ -139,5 +139,3 @@ function createRoom(opts) {
         return null;
     });
 }
-
-module.exports = createRoom;
diff --git a/src/dispatcher.js b/src/dispatcher.js
index 48c8dc86e9..f6bbea97d8 100644
--- a/src/dispatcher.js
+++ b/src/dispatcher.js
@@ -55,4 +55,4 @@ class MatrixDispatcher extends flux.Dispatcher {
 if (global.mxDispatcher === undefined) {
     global.mxDispatcher = new MatrixDispatcher();
 }
-module.exports = global.mxDispatcher;
+export default global.mxDispatcher;
diff --git a/src/email.js b/src/email.js
index 3fd535c849..6e2ed69bb7 100644
--- a/src/email.js
+++ b/src/email.js
@@ -16,8 +16,6 @@ limitations under the License.
 
 const EMAIL_ADDRESS_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i;
 
-module.exports = {
-    looksValid: function(email) {
-        return EMAIL_ADDRESS_REGEX.test(email);
-    },
-};
+export function looksValid(email) {
+    return EMAIL_ADDRESS_REGEX.test(email);
+}
diff --git a/src/extend.js b/src/extend.js
index 4b3f028a94..263d802ab6 100644
--- a/src/extend.js
+++ b/src/extend.js
@@ -16,11 +16,11 @@ limitations under the License.
 
 'use strict';
 
-module.exports = function(dest, src) {
+export default function(dest, src) {
     for (const i in src) {
         if (src.hasOwnProperty(i)) {
             dest[i] = src[i];
         }
     }
     return dest;
-};
+}
diff --git a/src/indexing/EventIndexPeg.js b/src/indexing/EventIndexPeg.js
index 75f0fa66ba..3746591b1f 100644
--- a/src/indexing/EventIndexPeg.js
+++ b/src/indexing/EventIndexPeg.js
@@ -110,4 +110,4 @@ class EventIndexPeg {
 if (!global.mxEventIndexPeg) {
     global.mxEventIndexPeg = new EventIndexPeg();
 }
-module.exports = global.mxEventIndexPeg;
+export default global.mxEventIndexPeg;
diff --git a/src/notifications/ContentRules.js b/src/notifications/ContentRules.js
index f7e722dbfe..8c285220c7 100644
--- a/src/notifications/ContentRules.js
+++ b/src/notifications/ContentRules.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,9 +17,9 @@ limitations under the License.
 
 'use strict';
 
-const PushRuleVectorState = require('./PushRuleVectorState');
+import {PushRuleVectorState} from "./PushRuleVectorState";
 
-module.exports = {
+export class ContentRules {
     /**
      * Extract the keyword rules from a list of rules, and parse them
      * into a form which is useful for Vector's UI.
@@ -30,7 +31,7 @@ module.exports = {
      *   externalRules: a list of other keyword rules, with states other than
      *      vectorState
      */
-    parseContentRules: function(rulesets) {
+    static parseContentRules(rulesets) {
         // first categorise the keyword rules in terms of their actions
         const contentRules = this._categoriseContentRules(rulesets);
 
@@ -79,9 +80,9 @@ module.exports = {
                 externalRules: contentRules.other,
             };
         }
-    },
+    }
 
-    _categoriseContentRules: function(rulesets) {
+    static _categoriseContentRules(rulesets) {
         const contentRules = {on: [], on_but_disabled: [], loud: [], loud_but_disabled: [], other: []};
         for (const kind in rulesets.global) {
             for (let i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
@@ -116,5 +117,5 @@ module.exports = {
             }
         }
         return contentRules;
-    },
-};
+    }
+}
diff --git a/src/notifications/NotificationUtils.js b/src/notifications/NotificationUtils.js
index 79c1b38f6d..bf393da060 100644
--- a/src/notifications/NotificationUtils.js
+++ b/src/notifications/NotificationUtils.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,14 +17,14 @@ limitations under the License.
 
 'use strict';
 
-module.exports = {
+export class NotificationUtils {
     // Encodes a dictionary of {
     //   "notify": true/false,
     //   "sound": string or undefined,
     //   "highlight: true/false,
     // }
     // to a list of push actions.
-    encodeActions: function(action) {
+    static encodeActions(action) {
         const notify = action.notify;
         const sound = action.sound;
         const highlight = action.highlight;
@@ -41,7 +42,7 @@ module.exports = {
         } else {
             return ["dont_notify"];
         }
-    },
+    }
 
     // Decode a list of actions to a dictionary of {
     //   "notify": true/false,
@@ -49,7 +50,7 @@ module.exports = {
     //   "highlight: true/false,
     // }
     // If the actions couldn't be decoded then returns null.
-    decodeActions: function(actions) {
+    static decodeActions(actions) {
         let notify = false;
         let sound = null;
         let highlight = false;
@@ -85,5 +86,5 @@ module.exports = {
             result.sound = sound;
         }
         return result;
-    },
-};
+    }
+}
diff --git a/src/notifications/PushRuleVectorState.js b/src/notifications/PushRuleVectorState.js
index f4ba365b6d..263226ce1c 100644
--- a/src/notifications/PushRuleVectorState.js
+++ b/src/notifications/PushRuleVectorState.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,42 +17,44 @@ limitations under the License.
 
 'use strict';
 
-const StandardActions = require('./StandardActions');
-const NotificationUtils = require('./NotificationUtils');
+import {StandardActions} from "./StandardActions";
+import {NotificationUtils} from "./NotificationUtils";
 
-const states = {
-    /** The push rule is disabled */
-    OFF: "off",
+export class PushRuleVectorState {
+    // Backwards compatibility (things should probably be using .states instead)
+    static OFF = "off";
+    static ON = "on";
+    static LOUD = "loud";
 
-    /** The user will receive push notification for this rule */
-    ON: "on",
-
-    /** The user will receive push notification for this rule with sound and
-        highlight if this is legitimate */
-    LOUD: "loud",
-};
-
-
-module.exports = {
     /**
      * Enum for state of a push rule as defined by the Vector UI.
      * @readonly
      * @enum {string}
      */
-    states: states,
+    static states = {
+        /** The push rule is disabled */
+        OFF: PushRuleVectorState.OFF,
+
+        /** The user will receive push notification for this rule */
+        ON: PushRuleVectorState.ON,
+
+        /** The user will receive push notification for this rule with sound and
+         highlight if this is legitimate */
+        LOUD: PushRuleVectorState.LOUD,
+    };
 
     /**
      * Convert a PushRuleVectorState to a list of actions
      *
      * @return [object] list of push-rule actions
      */
-    actionsFor: function(pushRuleVectorState) {
-        if (pushRuleVectorState === this.ON) {
+    static actionsFor(pushRuleVectorState) {
+        if (pushRuleVectorState === PushRuleVectorState.ON) {
             return StandardActions.ACTION_NOTIFY;
-        } else if (pushRuleVectorState === this.LOUD) {
+        } else if (pushRuleVectorState === PushRuleVectorState.LOUD) {
             return StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND;
         }
-    },
+    }
 
     /**
      * Convert a pushrule's actions to a PushRuleVectorState.
@@ -60,7 +63,7 @@ module.exports = {
      * category or in PushRuleVectorState.LOUD, regardless of its enabled
      * state. Returns null if it does not match these categories.
      */
-    contentRuleVectorStateKind: function(rule) {
+    static contentRuleVectorStateKind(rule) {
         const decoded = NotificationUtils.decodeActions(rule.actions);
 
         if (!decoded) {
@@ -78,16 +81,12 @@ module.exports = {
         let stateKind = null;
         switch (tweaks) {
             case 0:
-                stateKind = this.ON;
+                stateKind = PushRuleVectorState.ON;
                 break;
             case 2:
-                stateKind = this.LOUD;
+                stateKind = PushRuleVectorState.LOUD;
                 break;
         }
         return stateKind;
-    },
-};
-
-for (const k in states) {
-    module.exports[k] = states[k];
+    }
 }
diff --git a/src/notifications/StandardActions.js b/src/notifications/StandardActions.js
index 15f645d5f7..b54cea332a 100644
--- a/src/notifications/StandardActions.js
+++ b/src/notifications/StandardActions.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,16 +17,16 @@ limitations under the License.
 
 'use strict';
 
-const NotificationUtils = require('./NotificationUtils');
+import {NotificationUtils} from "./NotificationUtils";
 
 const encodeActions = NotificationUtils.encodeActions;
 
-module.exports = {
-    ACTION_NOTIFY: encodeActions({notify: true}),
-    ACTION_NOTIFY_DEFAULT_SOUND: encodeActions({notify: true, sound: "default"}),
-    ACTION_NOTIFY_RING_SOUND: encodeActions({notify: true, sound: "ring"}),
-    ACTION_HIGHLIGHT: encodeActions({notify: true, highlight: true}),
-    ACTION_HIGHLIGHT_DEFAULT_SOUND: encodeActions({notify: true, sound: "default", highlight: true}),
-    ACTION_DONT_NOTIFY: encodeActions({notify: false}),
-    ACTION_DISABLED: null,
-};
+export class StandardActions {
+    static ACTION_NOTIFY = encodeActions({notify: true});
+    static ACTION_NOTIFY_DEFAULT_SOUND = encodeActions({notify: true, sound: "default"});
+    static ACTION_NOTIFY_RING_SOUND = encodeActions({notify: true, sound: "ring"});
+    static ACTION_HIGHLIGHT = encodeActions({notify: true, highlight: true});
+    static ACTION_HIGHLIGHT_DEFAULT_SOUND = encodeActions({notify: true, sound: "default", highlight: true});
+    static ACTION_DONT_NOTIFY = encodeActions({notify: false});
+    static ACTION_DISABLED = null;
+}
diff --git a/src/notifications/VectorPushRulesDefinitions.js b/src/notifications/VectorPushRulesDefinitions.js
index b15fb4ccd7..98d197a004 100644
--- a/src/notifications/VectorPushRulesDefinitions.js
+++ b/src/notifications/VectorPushRulesDefinitions.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -17,10 +18,9 @@ limitations under the License.
 'use strict';
 
 import { _td } from '../languageHandler';
-
-const StandardActions = require('./StandardActions');
-const PushRuleVectorState = require('./PushRuleVectorState');
-const { decodeActions } = require('./NotificationUtils');
+import {StandardActions} from "./StandardActions";
+import {PushRuleVectorState} from "./PushRuleVectorState";
+import {NotificationUtils} from "./NotificationUtils";
 
 class VectorPushRuleDefinition {
     constructor(opts) {
@@ -51,8 +51,8 @@ class VectorPushRuleDefinition {
                 // value: true vs. unspecified for highlight (which defaults to
                 // true, making them equivalent).
                 if (enabled &&
-                        JSON.stringify(decodeActions(rule.actions)) ===
-                        JSON.stringify(decodeActions(vectorStateToActions))) {
+                        JSON.stringify(NotificationUtils.decodeActions(rule.actions)) ===
+                        JSON.stringify(NotificationUtils.decodeActions(vectorStateToActions))) {
                     return state;
                 }
             }
@@ -68,7 +68,7 @@ class VectorPushRuleDefinition {
 /**
  * The descriptions of rules managed by the Vector UI.
  */
-module.exports = {
+export const VectorPushRulesDefinitions = {
     // Messages containing user's display name
     ".m.rule.contains_display_name": new VectorPushRuleDefinition({
         kind: "override",
diff --git a/src/notifications/index.js b/src/notifications/index.js
index 8ed77e9d41..7c400ad8b3 100644
--- a/src/notifications/index.js
+++ b/src/notifications/index.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,9 +17,7 @@ limitations under the License.
 
 'use strict';
 
-module.exports = {
-    NotificationUtils: require('./NotificationUtils'),
-    PushRuleVectorState: require('./PushRuleVectorState'),
-    VectorPushRulesDefinitions: require('./VectorPushRulesDefinitions'),
-    ContentRules: require('./ContentRules'),
-};
+export * from "./NotificationUtils";
+export * from "./PushRuleVectorState";
+export * from "./VectorPushRulesDefinitions";
+export * from "./ContentRules";
diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js
index 47bab38079..a9d17e77c9 100644
--- a/src/rageshake/rageshake.js
+++ b/src/rageshake/rageshake.js
@@ -432,77 +432,73 @@ function selectQuery(store, keyRange, resultMapper) {
     });
 }
 
-
-module.exports = {
-
-    /**
-     * Configure rage shaking support for sending bug reports.
-     * Modifies globals.
-     * @return {Promise} Resolves when set up.
-     */
-    init: function() {
-        if (global.mx_rage_initPromise) {
-            return global.mx_rage_initPromise;
-        }
-        global.mx_rage_logger = new ConsoleLogger();
-        global.mx_rage_logger.monkeyPatch(window.console);
-
-        // just *accessing* indexedDB throws an exception in firefox with
-        // indexeddb disabled.
-        let indexedDB;
-        try {
-            indexedDB = window.indexedDB;
-        } catch (e) {}
-
-        if (indexedDB) {
-            global.mx_rage_store = new IndexedDBLogStore(indexedDB, global.mx_rage_logger);
-            global.mx_rage_initPromise = global.mx_rage_store.connect();
-            return global.mx_rage_initPromise;
-        }
-        global.mx_rage_initPromise = Promise.resolve();
+/**
+ * Configure rage shaking support for sending bug reports.
+ * Modifies globals.
+ * @return {Promise} Resolves when set up.
+ */
+export function init() {
+    if (global.mx_rage_initPromise) {
         return global.mx_rage_initPromise;
-    },
+    }
+    global.mx_rage_logger = new ConsoleLogger();
+    global.mx_rage_logger.monkeyPatch(window.console);
 
-    flush: function() {
-        if (!global.mx_rage_store) {
-            return;
-        }
-        global.mx_rage_store.flush();
-    },
+    // just *accessing* indexedDB throws an exception in firefox with
+    // indexeddb disabled.
+    let indexedDB;
+    try {
+        indexedDB = window.indexedDB;
+    } catch (e) {}
 
-    /**
-     * Clean up old logs.
-     * @return Promise Resolves if cleaned logs.
-     */
-    cleanup: async function() {
-        if (!global.mx_rage_store) {
-            return;
-        }
-        await global.mx_rage_store.consume();
-    },
+    if (indexedDB) {
+        global.mx_rage_store = new IndexedDBLogStore(indexedDB, global.mx_rage_logger);
+        global.mx_rage_initPromise = global.mx_rage_store.connect();
+        return global.mx_rage_initPromise;
+    }
+    global.mx_rage_initPromise = Promise.resolve();
+    return global.mx_rage_initPromise;
+}
 
-    /**
-     * Get a recent snapshot of the logs, ready for attaching to a bug report
-     *
-     * @return {Array<{lines: string, id, string}>}  list of log data
-     */
-    getLogsForReport: async function() {
-        if (!global.mx_rage_logger) {
-            throw new Error(
-                "No console logger, did you forget to call init()?",
-            );
-        }
-        // If in incognito mode, store is null, but we still want bug report
-        // sending to work going off the in-memory console logs.
-        if (global.mx_rage_store) {
-            // flush most recent logs
-            await global.mx_rage_store.flush();
-            return await global.mx_rage_store.consume();
-        } else {
-            return [{
-                lines: global.mx_rage_logger.flush(true),
-                id: "-",
-            }];
-        }
-    },
-};
+export function flush() {
+    if (!global.mx_rage_store) {
+        return;
+    }
+    global.mx_rage_store.flush();
+}
+
+/**
+ * Clean up old logs.
+ * @return Promise Resolves if cleaned logs.
+ */
+export async function cleanup() {
+    if (!global.mx_rage_store) {
+        return;
+    }
+    await global.mx_rage_store.consume();
+}
+
+/**
+ * Get a recent snapshot of the logs, ready for attaching to a bug report
+ *
+ * @return {Array<{lines: string, id, string}>}  list of log data
+ */
+export async function getLogsForReport() {
+    if (!global.mx_rage_logger) {
+        throw new Error(
+            "No console logger, did you forget to call init()?",
+        );
+    }
+    // If in incognito mode, store is null, but we still want bug report
+    // sending to work going off the in-memory console logs.
+    if (global.mx_rage_store) {
+        // flush most recent logs
+        await global.mx_rage_store.flush();
+        return await global.mx_rage_store.consume();
+    } else {
+        return [{
+            lines: global.mx_rage_logger.flush(true),
+            id: "-",
+        }];
+    }
+}
diff --git a/src/rageshake/submit-rageshake.js b/src/rageshake/submit-rageshake.js
index 457958eb82..0e5db7c54c 100644
--- a/src/rageshake/submit-rageshake.js
+++ b/src/rageshake/submit-rageshake.js
@@ -22,7 +22,7 @@ import MatrixClientPeg from '../MatrixClientPeg';
 import PlatformPeg from '../PlatformPeg';
 import { _t } from '../languageHandler';
 
-import rageshake from './rageshake';
+import * as rageshake from './rageshake';
 
 
 // polyfill textencoder if necessary
diff --git a/src/stores/GroupStore.js b/src/stores/GroupStore.js
index 637e87b728..3ba0e04631 100644
--- a/src/stores/GroupStore.js
+++ b/src/stores/GroupStore.js
@@ -340,4 +340,4 @@ let singletonGroupStore = null;
 if (!singletonGroupStore) {
     singletonGroupStore = new GroupStore();
 }
-module.exports = singletonGroupStore;
+export default singletonGroupStore;
diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js
index 91dcf0aebb..904f29f7b3 100644
--- a/src/stores/LifecycleStore.js
+++ b/src/stores/LifecycleStore.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2017 Vector Creations Ltd
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -79,4 +80,4 @@ let singletonLifecycleStore = null;
 if (!singletonLifecycleStore) {
     singletonLifecycleStore = new LifecycleStore();
 }
-module.exports = singletonLifecycleStore;
+export default singletonLifecycleStore;
diff --git a/src/stores/MessageComposerStore.js b/src/stores/MessageComposerStore.js
index ab2dbfedec..3c7440e10b 100644
--- a/src/stores/MessageComposerStore.js
+++ b/src/stores/MessageComposerStore.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017, 2018 Vector Creations Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -63,4 +64,4 @@ let singletonMessageComposerStore = null;
 if (!singletonMessageComposerStore) {
     singletonMessageComposerStore = new MessageComposerStore();
 }
-module.exports = singletonMessageComposerStore;
+export default singletonMessageComposerStore;
diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js
index a3caf876ef..eb2d539bb1 100644
--- a/src/stores/RoomViewStore.js
+++ b/src/stores/RoomViewStore.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2017 Vector Creations Ltd
 Copyright 2017, 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -357,4 +358,4 @@ let singletonRoomViewStore = null;
 if (!singletonRoomViewStore) {
     singletonRoomViewStore = new RoomViewStore();
 }
-module.exports = singletonRoomViewStore;
+export default singletonRoomViewStore;
diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js
index ad58f1e93d..f38bc046d0 100644
--- a/src/stores/SessionStore.js
+++ b/src/stores/SessionStore.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2017 Vector Creations Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -86,4 +87,4 @@ let singletonSessionStore = null;
 if (!singletonSessionStore) {
     singletonSessionStore = new SessionStore();
 }
-module.exports = singletonSessionStore;
+export default singletonSessionStore;
diff --git a/src/stores/WidgetEchoStore.js b/src/stores/WidgetEchoStore.js
index 0d14ed1d60..33fa45c635 100644
--- a/src/stores/WidgetEchoStore.js
+++ b/src/stores/WidgetEchoStore.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -105,4 +106,4 @@ let singletonWidgetEchoStore = null;
 if (!singletonWidgetEchoStore) {
     singletonWidgetEchoStore = new WidgetEchoStore();
 }
-module.exports = singletonWidgetEchoStore;
+export default singletonWidgetEchoStore;
diff --git a/test/components/stub-component.js b/test/components/stub-component.js
index 9264792ffb..5638ada09d 100644
--- a/test/components/stub-component.js
+++ b/test/components/stub-component.js
@@ -4,7 +4,7 @@
 import React from 'react';
 import createReactClass from 'create-react-class';
 
-module.exports = function(opts) {
+export default function(opts) {
     opts = opts || {};
     if (!opts.displayName) {
         opts.displayName = 'StubComponent';
diff --git a/test/end-to-end-tests/src/logbuffer.js b/test/end-to-end-tests/src/logbuffer.js
index d586dc8b84..db4be33e8d 100644
--- a/test/end-to-end-tests/src/logbuffer.js
+++ b/test/end-to-end-tests/src/logbuffer.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-module.exports = class LogBuffer {
+export default class LogBuffer {
     constructor(page, eventName, eventMapper, reduceAsync=false, initialValue = "") {
         this.buffer = initialValue;
         page.on(eventName, (arg) => {
diff --git a/test/end-to-end-tests/src/logger.js b/test/end-to-end-tests/src/logger.js
index 283d07f163..42a9544e4d 100644
--- a/test/end-to-end-tests/src/logger.js
+++ b/test/end-to-end-tests/src/logger.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-module.exports = class Logger {
+export default class Logger {
     constructor(username) {
         this.indent = 0;
         this.username = username;
diff --git a/test/end-to-end-tests/src/rest/creator.js b/test/end-to-end-tests/src/rest/creator.js
index fde54014b2..c4ddee0581 100644
--- a/test/end-to-end-tests/src/rest/creator.js
+++ b/test/end-to-end-tests/src/rest/creator.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -31,7 +32,7 @@ function execAsync(command, options) {
     });
 }
 
-module.exports = class RestSessionCreator {
+export default class RestSessionCreator {
     constructor(synapseSubdir, hsUrl, cwd) {
         this.synapseSubdir = synapseSubdir;
         this.hsUrl = hsUrl;
diff --git a/test/end-to-end-tests/src/rest/multi.js b/test/end-to-end-tests/src/rest/multi.js
index e58b9f3f57..d4cd5c765c 100644
--- a/test/end-to-end-tests/src/rest/multi.js
+++ b/test/end-to-end-tests/src/rest/multi.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@ limitations under the License.
 
 const Logger = require('../logger');
 
-module.exports = class RestMultiSession {
+export default class RestMultiSession {
     constructor(sessions, groupName) {
         this.log = new Logger(groupName);
         this.sessions = sessions;
diff --git a/test/end-to-end-tests/src/rest/room.js b/test/end-to-end-tests/src/rest/room.js
index 429a29c31a..b3ba725336 100644
--- a/test/end-to-end-tests/src/rest/room.js
+++ b/test/end-to-end-tests/src/rest/room.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -17,7 +18,7 @@ limitations under the License.
 const uuidv4 = require('uuid/v4');
 
 /* no pun intented */
-module.exports = class RestRoom {
+export default class RestRoom {
     constructor(session, roomId, log) {
         this.session = session;
         this._roomId = roomId;
diff --git a/test/end-to-end-tests/src/rest/session.js b/test/end-to-end-tests/src/rest/session.js
index 5b97824f5c..344493968c 100644
--- a/test/end-to-end-tests/src/rest/session.js
+++ b/test/end-to-end-tests/src/rest/session.js
@@ -19,7 +19,7 @@ const Logger = require('../logger');
 const RestRoom = require('./room');
 const {approveConsent} = require('./consent');
 
-module.exports = class RestSession {
+export default class RestSession {
     constructor(credentials) {
         this.log = new Logger(credentials.userId);
         this._credentials = credentials;
diff --git a/test/end-to-end-tests/src/scenarios/directory.js b/test/end-to-end-tests/src/scenarios/directory.js
index 3ae728a5b7..cf995ae1a8 100644
--- a/test/end-to-end-tests/src/scenarios/directory.js
+++ b/test/end-to-end-tests/src/scenarios/directory.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ const {receiveMessage} = require('../usecases/timeline');
 const {createRoom} = require('../usecases/create-room');
 const changeRoomSettings = require('../usecases/room-settings');
 
-module.exports = async function roomDirectoryScenarios(alice, bob) {
+export default async function roomDirectoryScenarios(alice, bob) {
     console.log(" creating a public room and join through directory:");
     const room = 'test';
     await createRoom(alice, room);
diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js
index 8df374bacb..2a002da66b 100644
--- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js
+++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -23,7 +24,7 @@ const changeRoomSettings = require('../usecases/room-settings');
 const {startSasVerifcation, acceptSasVerification} = require('../usecases/verify');
 const assert = require('assert');
 
-module.exports = async function e2eEncryptionScenarios(alice, bob) {
+export default async function e2eEncryptionScenarios(alice, bob) {
     console.log(" creating an e2e encrypted room and join through invite:");
     const room = "secrets";
     await createRoom(bob, room);
diff --git a/test/end-to-end-tests/src/scenarios/lazy-loading.js b/test/end-to-end-tests/src/scenarios/lazy-loading.js
index be5a91bb71..651397e426 100644
--- a/test/end-to-end-tests/src/scenarios/lazy-loading.js
+++ b/test/end-to-end-tests/src/scenarios/lazy-loading.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -27,7 +28,7 @@ const {getMembersInMemberlist} = require('../usecases/memberlist');
 const changeRoomSettings = require('../usecases/room-settings');
 const assert = require('assert');
 
-module.exports = async function lazyLoadingScenarios(alice, bob, charlies) {
+export default async function lazyLoadingScenarios(alice, bob, charlies) {
     console.log(" creating a room for lazy loading member scenarios:");
     const charly1to5 = charlies.slice("charly-1..5", 0, 5);
     const charly6to10 = charlies.slice("charly-6..10", 5);
diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js
index 65cec6fef0..b17e55efa4 100644
--- a/test/end-to-end-tests/src/session.js
+++ b/test/end-to-end-tests/src/session.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@ const {delay} = require('./util');
 
 const DEFAULT_TIMEOUT = 20000;
 
-module.exports = class RiotSession {
+export default class RiotSession {
     constructor(browser, page, username, riotserver, hsUrl) {
         this.browser = browser;
         this.page = page;
diff --git a/test/end-to-end-tests/src/usecases/accept-invite.js b/test/end-to-end-tests/src/usecases/accept-invite.js
index 085c60aa6a..d17f583a77 100644
--- a/test/end-to-end-tests/src/usecases/accept-invite.js
+++ b/test/end-to-end-tests/src/usecases/accept-invite.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-module.exports = async function acceptInvite(session, name) {
+export default async function acceptInvite(session, name) {
     session.log.step(`accepts "${name}" invite`);
     //TODO: brittle selector
     const invitesHandles = await session.queryAll('.mx_RoomTile_name.mx_RoomTile_invite');
diff --git a/test/end-to-end-tests/src/usecases/create-room.js b/test/end-to-end-tests/src/usecases/create-room.js
index 75abdc78f4..7ca3826c71 100644
--- a/test/end-to-end-tests/src/usecases/create-room.js
+++ b/test/end-to-end-tests/src/usecases/create-room.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,12 +15,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-async function openRoomDirectory(session) {
+export async function openRoomDirectory(session) {
     const roomDirectoryButton = await session.query('.mx_LeftPanel_explore .mx_AccessibleButton');
     await roomDirectoryButton.click();
 }
 
-async function createRoom(session, roomName) {
+export async function createRoom(session, roomName) {
     session.log.step(`creates room "${roomName}"`);
 
     const roomListHeaders = await session.queryAll('.mx_RoomSubList_labelContainer');
@@ -42,5 +43,3 @@ async function createRoom(session, roomName) {
     await session.query('.mx_MessageComposer');
     session.log.done();
 }
-
-module.exports = {openRoomDirectory, createRoom};
diff --git a/test/end-to-end-tests/src/usecases/dialog.js b/test/end-to-end-tests/src/usecases/dialog.js
index 7b5d4d09fa..72d024fc79 100644
--- a/test/end-to-end-tests/src/usecases/dialog.js
+++ b/test/end-to-end-tests/src/usecases/dialog.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,20 +17,20 @@ limitations under the License.
 
 const assert = require('assert');
 
-async function assertDialog(session, expectedTitle) {
+export async function assertDialog(session, expectedTitle) {
     const titleElement = await session.query(".mx_Dialog .mx_Dialog_title");
     const dialogHeader = await session.innerText(titleElement);
     assert(dialogHeader, expectedTitle);
 }
 
-async function acceptDialog(session, expectedTitle) {
+export async function acceptDialog(session, expectedTitle) {
     const foundDialog = await acceptDialogMaybe(session, expectedTitle);
     if (!foundDialog) {
         throw new Error("could not find a dialog");
     }
 }
 
-async function acceptDialogMaybe(session, expectedTitle) {
+export async function acceptDialogMaybe(session, expectedTitle) {
     let primaryButton = null;
     try {
         primaryButton = await session.query(".mx_Dialog .mx_Dialog_primary");
@@ -42,9 +43,3 @@ async function acceptDialogMaybe(session, expectedTitle) {
     await primaryButton.click();
     return true;
 }
-
-module.exports = {
-    assertDialog,
-    acceptDialog,
-    acceptDialogMaybe,
-};
diff --git a/test/end-to-end-tests/src/usecases/invite.js b/test/end-to-end-tests/src/usecases/invite.js
index 814ecd30a6..fc91e4ce16 100644
--- a/test/end-to-end-tests/src/usecases/invite.js
+++ b/test/end-to-end-tests/src/usecases/invite.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-module.exports = async function invite(session, userId) {
+export default async function invite(session, userId) {
     session.log.step(`invites "${userId}" to room`);
     await session.delay(1000);
     const memberPanelButton = await session.query(".mx_RightPanel_membersButton");
diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js
index bc292a0768..4fbc134598 100644
--- a/test/end-to-end-tests/src/usecases/join.js
+++ b/test/end-to-end-tests/src/usecases/join.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@ limitations under the License.
 
 const {openRoomDirectory} = require('./create-room');
 
-module.exports = async function join(session, roomName) {
+export default async function join(session, roomName) {
     session.log.step(`joins room "${roomName}"`);
     await openRoomDirectory(session);
     const roomInput = await session.query('.mx_DirectorySearchBox input');
diff --git a/test/end-to-end-tests/src/usecases/room-settings.js b/test/end-to-end-tests/src/usecases/room-settings.js
index 7655d2d066..d853cf92e4 100644
--- a/test/end-to-end-tests/src/usecases/room-settings.js
+++ b/test/end-to-end-tests/src/usecases/room-settings.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -29,7 +30,7 @@ async function setSettingsToggle(session, toggle, enabled) {
     }
 }
 
-module.exports = async function changeRoomSettings(session, settings) {
+export default async function changeRoomSettings(session, settings) {
     session.log.startGroup(`changes the room settings`);
     /// XXX delay is needed here, possibly because the header is being rerendered
     /// click doesn't do anything otherwise
diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js
index fd2b948572..381b87ec9e 100644
--- a/test/end-to-end-tests/src/usecases/signup.js
+++ b/test/end-to-end-tests/src/usecases/signup.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-module.exports = async function signup(session, username, password, homeserver) {
+export default async function signup(session, username, password, homeserver) {
     session.log.step("signs up");
     await session.goto(session.url('/#/register'));
     // change the homeserver by clicking the advanced section

From 4aec432b30209bfe633221c5a93c13140e69e213 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 17:57:50 -0700
Subject: [PATCH 32/86] Convert the more complicated CommonJS exports to
 ES6-style

---
 src/CallHandler.js                            |  6 +--
 src/ObjectUtils.js                            |  9 ++--
 src/Resend.js                                 | 42 ++++++++++---------
 src/VectorConferenceHandler.js                | 28 ++++++-------
 src/components/structures/RoomView.js         |  4 +-
 src/components/views/rooms/EventTile.js       |  8 ++--
 src/index.js                                  | 13 +++---
 test/end-to-end-tests/src/rest/consent.js     |  5 ++-
 .../src/usecases/memberlist.js                | 13 +++---
 .../end-to-end-tests/src/usecases/settings.js |  9 ++--
 .../end-to-end-tests/src/usecases/timeline.js | 13 +++---
 test/end-to-end-tests/src/usecases/verify.js  |  9 ++--
 test/end-to-end-tests/src/util.js             |  9 ++--
 test/mock-clock.js                            |  9 ++--
 14 files changed, 91 insertions(+), 86 deletions(-)

diff --git a/src/CallHandler.js b/src/CallHandler.js
index eb5a5c1c8e..7dabaa3fc1 100644
--- a/src/CallHandler.js
+++ b/src/CallHandler.js
@@ -302,7 +302,7 @@ function _onAction(payload) {
     switch (payload.action) {
         case 'place_call':
             {
-                if (module.exports.getAnyActiveCall()) {
+                if (callHandler.getAnyActiveCall()) {
                     const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                     Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
                         title: _t('Existing Call'),
@@ -355,7 +355,7 @@ function _onAction(payload) {
             break;
         case 'incoming_call':
             {
-                if (module.exports.getAnyActiveCall()) {
+                if (callHandler.getAnyActiveCall()) {
                     // ignore multiple incoming calls. in future, we may want a line-1/line-2 setup.
                     // we avoid rejecting with "busy" in case the user wants to answer it on a different device.
                     // in future we could signal a "local busy" as a warning to the caller.
@@ -523,7 +523,7 @@ if (!global.mxCallHandler) {
 
 const callHandler = {
     getCallForRoom: function(roomId) {
-        let call = module.exports.getCall(roomId);
+        let call = callHandler.getCall(roomId);
         if (call) return call;
 
         if (ConferenceHandler) {
diff --git a/src/ObjectUtils.js b/src/ObjectUtils.js
index 07d8b465af..24dfe61d68 100644
--- a/src/ObjectUtils.js
+++ b/src/ObjectUtils.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ limitations under the License.
  * @return {Object[]} An array of objects with the form:
  * { key: $KEY, val: $VALUE, place: "add|del" }
  */
-module.exports.getKeyValueArrayDiffs = function(before, after) {
+export function getKeyValueArrayDiffs(before, after) {
     const results = [];
     const delta = {};
     Object.keys(before).forEach(function(beforeKey) {
@@ -76,7 +77,7 @@ module.exports.getKeyValueArrayDiffs = function(before, after) {
     });
 
     return results;
-};
+}
 
 /**
  * Shallow-compare two objects for equality: each key and value must be identical
@@ -84,7 +85,7 @@ module.exports.getKeyValueArrayDiffs = function(before, after) {
  * @param {Object} objB Second object to compare against the first
  * @return {boolean} whether the two objects have same key=values
  */
-module.exports.shallowEqual = function(objA, objB) {
+export function shallowEqual(objA, objB) {
     if (objA === objB) {
         return true;
     }
@@ -109,4 +110,4 @@ module.exports.shallowEqual = function(objA, objB) {
     }
 
     return true;
-};
+}
diff --git a/src/Resend.js b/src/Resend.js
index 51ec804c01..563171d73e 100644
--- a/src/Resend.js
+++ b/src/Resend.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -18,40 +19,43 @@ import MatrixClientPeg from './MatrixClientPeg';
 import dis from './dispatcher';
 import { EventStatus } from 'matrix-js-sdk';
 
-module.exports = {
-    resendUnsentEvents: function(room) {
-        room.getPendingEvents().filter(function(ev) {
+export default class Resend {
+    static resendUnsentEvents(room) {
+        room.getPendingEvents().filter(function (ev) {
             return ev.status === EventStatus.NOT_SENT;
-        }).forEach(function(event) {
-            module.exports.resend(event);
+        }).forEach(function (event) {
+            Resend.resend(event);
         });
-    },
-    cancelUnsentEvents: function(room) {
-        room.getPendingEvents().filter(function(ev) {
+    }
+
+    static cancelUnsentEvents(room) {
+        room.getPendingEvents().filter(function (ev) {
             return ev.status === EventStatus.NOT_SENT;
-        }).forEach(function(event) {
-            module.exports.removeFromQueue(event);
+        }).forEach(function (event) {
+            Resend.removeFromQueue(event);
         });
-    },
-    resend: function(event) {
+    }
+
+    static resend(event) {
         const room = MatrixClientPeg.get().getRoom(event.getRoomId());
-        MatrixClientPeg.get().resendEvent(event, room).then(function(res) {
+        MatrixClientPeg.get().resendEvent(event, room).then(function (res) {
             dis.dispatch({
                 action: 'message_sent',
                 event: event,
             });
-        }, function(err) {
+        }, function (err) {
             // XXX: temporary logging to try to diagnose
             // https://github.com/vector-im/riot-web/issues/3148
-            console.log('Resend got send failure: ' + err.name + '('+err+')');
+            console.log('Resend got send failure: ' + err.name + '(' + err + ')');
 
             dis.dispatch({
                 action: 'message_send_failed',
                 event: event,
             });
         });
-    },
-    removeFromQueue: function(event) {
+    }
+
+    static removeFromQueue(event) {
         MatrixClientPeg.get().cancelPendingEvent(event);
-    },
-};
+    }
+}
diff --git a/src/VectorConferenceHandler.js b/src/VectorConferenceHandler.js
index e0e333a371..debb5f94b2 100644
--- a/src/VectorConferenceHandler.js
+++ b/src/VectorConferenceHandler.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -28,10 +29,10 @@ import MatrixClientPeg from "./MatrixClientPeg";
 const USER_PREFIX = "fs_";
 const DOMAIN = "matrix.org";
 
-function ConferenceCall(matrixClient, groupChatRoomId) {
+export function ConferenceCall(matrixClient, groupChatRoomId) {
     this.client = matrixClient;
     this.groupRoomId = groupChatRoomId;
-    this.confUserId = module.exports.getConferenceUserIdForRoom(this.groupRoomId);
+    this.confUserId = getConferenceUserIdForRoom(this.groupRoomId);
 }
 
 ConferenceCall.prototype.setup = function() {
@@ -90,7 +91,7 @@ ConferenceCall.prototype._getConferenceUserRoom = function() {
  * @param {string} userId The user ID to check.
  * @return {boolean} True if it is a conference bot.
  */
-module.exports.isConferenceUser = function(userId) {
+export function isConferenceUser(userId) {
     if (userId.indexOf("@" + USER_PREFIX) !== 0) {
         return false;
     }
@@ -101,26 +102,26 @@ module.exports.isConferenceUser = function(userId) {
         return /^!.+:.+/.test(decoded);
     }
     return false;
-};
+}
 
-module.exports.getConferenceUserIdForRoom = function(roomId) {
+export function getConferenceUserIdForRoom(roomId) {
     // abuse browserify's core node Buffer support (strip padding ='s)
     const base64RoomId = new Buffer(roomId).toString("base64").replace(/=/g, "");
     return "@" + USER_PREFIX + base64RoomId + ":" + DOMAIN;
-};
+}
 
-module.exports.createNewMatrixCall = function(client, roomId) {
+export function createNewMatrixCall(client, roomId) {
     const confCall = new ConferenceCall(
         client, roomId,
     );
     return confCall.setup();
-};
+}
 
-module.exports.getConferenceCallForRoom = function(roomId) {
+export function getConferenceCallForRoom(roomId) {
     // search for a conference 1:1 call for this group chat room ID
     const activeCall = CallHandler.getAnyActiveCall();
     if (activeCall && activeCall.confUserId) {
-        const thisRoomConfUserId = module.exports.getConferenceUserIdForRoom(
+        const thisRoomConfUserId = getConferenceUserIdForRoom(
             roomId,
         );
         if (thisRoomConfUserId === activeCall.confUserId) {
@@ -128,8 +129,7 @@ module.exports.getConferenceCallForRoom = function(roomId) {
         }
     }
     return null;
-};
+}
 
-module.exports.ConferenceCall = ConferenceCall;
-
-module.exports.slot = 'conference';
+// TODO: Document this.
+export const slot = 'conference';
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 3f9d680503..c2311586b3 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -66,7 +66,7 @@ if (DEBUG) {
     debuglog = console.log.bind(console);
 }
 
-const RoomContext = PropTypes.shape({
+export const RoomContext = PropTypes.shape({
     canReact: PropTypes.bool.isRequired,
     canReply: PropTypes.bool.isRequired,
     room: PropTypes.instanceOf(Room),
@@ -2002,5 +2002,3 @@ export default createReactClass({
         );
     },
 });
-
-module.exports.RoomContext = RoomContext;
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 8f645522a3..8b8c60e402 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -75,7 +75,7 @@ for (const evType of ALL_RULE_TYPES) {
     stateEventTileTypes[evType] = 'messages.TextualEvent';
 }
 
-function getHandlerTile(ev) {
+export function getHandlerTile(ev) {
     const type = ev.getType();
 
     // don't show verification requests we're not involved in,
@@ -879,7 +879,7 @@ function isMessageEvent(ev) {
     return (messageTypes.includes(ev.getType()));
 }
 
-module.exports.haveTileForEvent = function(e) {
+export function haveTileForEvent(e) {
     // Only messages have a tile (black-rectangle) if redacted
     if (e.isRedacted() && !isMessageEvent(e)) return false;
 
@@ -895,7 +895,7 @@ module.exports.haveTileForEvent = function(e) {
     } else {
         return true;
     }
-};
+}
 
 function E2ePadlockUndecryptable(props) {
     return (
@@ -964,5 +964,3 @@ class E2ePadlock extends React.Component {
         );
     }
 }
-
-module.exports.getHandlerTile = getHandlerTile;
diff --git a/src/index.js b/src/index.js
index 7d0547d9c9..008e15ad90 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,14 +17,14 @@ limitations under the License.
 
 import Skinner from './Skinner';
 
-module.exports.loadSkin = function(skinObject) {
+export function loadSkin(skinObject) {
     Skinner.load(skinObject);
-};
+}
 
-module.exports.resetSkin = function() {
+export function resetSkin() {
     Skinner.reset();
-};
+}
 
-module.exports.getComponent = function(componentName) {
+export function getComponent(componentName) {
     return Skinner.getComponent(componentName);
-};
+}
diff --git a/test/end-to-end-tests/src/rest/consent.js b/test/end-to-end-tests/src/rest/consent.js
index 1e36f541a3..5c424cd6e8 100644
--- a/test/end-to-end-tests/src/rest/consent.js
+++ b/test/end-to-end-tests/src/rest/consent.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -18,7 +19,7 @@ const request = require('request-promise-native');
 const cheerio = require('cheerio');
 const url = require("url");
 
-module.exports.approveConsent = async function(consentUrl) {
+export async function approveConsent(consentUrl) {
     const body = await request.get(consentUrl);
     const doc = cheerio.load(body);
     const v = doc("input[name=v]").val();
@@ -27,4 +28,4 @@ module.exports.approveConsent = async function(consentUrl) {
     const formAction = doc("form").attr("action");
     const absAction = url.resolve(consentUrl, formAction);
     await request.post(absAction).form({v, u, h});
-};
+}
diff --git a/test/end-to-end-tests/src/usecases/memberlist.js b/test/end-to-end-tests/src/usecases/memberlist.js
index 42601b6610..8d2aacf35c 100644
--- a/test/end-to-end-tests/src/usecases/memberlist.js
+++ b/test/end-to-end-tests/src/usecases/memberlist.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-async function openMemberInfo(session, name) {
+export async function openMemberInfo(session, name) {
     const membersAndNames = await getMembersInMemberlist(session);
     const matchingLabel = membersAndNames.filter((m) => {
         return m.displayName === name;
@@ -24,9 +25,7 @@ async function openMemberInfo(session, name) {
     await matchingLabel.click();
 }
 
-module.exports.openMemberInfo = openMemberInfo;
-
-module.exports.verifyDeviceForUser = async function(session, name, expectedDevice) {
+export async function verifyDeviceForUser(session, name, expectedDevice) {
     session.log.step(`verifies e2e device for ${name}`);
     const membersAndNames = await getMembersInMemberlist(session);
     const matchingLabel = membersAndNames.filter((m) => {
@@ -59,9 +58,9 @@ module.exports.verifyDeviceForUser = async function(session, name, expectedDevic
     const closeMemberInfo = await session.query(".mx_MemberInfo_cancel");
     await closeMemberInfo.click();
     session.log.done();
-};
+}
 
-async function getMembersInMemberlist(session) {
+export async function getMembersInMemberlist(session) {
     const memberPanelButton = await session.query(".mx_RightPanel_membersButton");
     try {
         await session.query(".mx_RightPanel_headerButton_highlight", 500);
@@ -78,5 +77,3 @@ async function getMembersInMemberlist(session) {
         return {label: el, displayName: await session.innerText(el)};
     }));
 }
-
-module.exports.getMembersInMemberlist = getMembersInMemberlist;
diff --git a/test/end-to-end-tests/src/usecases/settings.js b/test/end-to-end-tests/src/usecases/settings.js
index ec675157f2..411ec3b497 100644
--- a/test/end-to-end-tests/src/usecases/settings.js
+++ b/test/end-to-end-tests/src/usecases/settings.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -28,7 +29,7 @@ async function openSettings(session, section) {
     }
 }
 
-module.exports.enableLazyLoading = async function(session) {
+export async function enableLazyLoading(session) {
     session.log.step(`enables lazy loading of members in the lab settings`);
     const settingsButton = await session.query('.mx_BottomLeftMenu_settings');
     await settingsButton.click();
@@ -38,9 +39,9 @@ module.exports.enableLazyLoading = async function(session) {
     const closeButton = await session.query(".mx_RoomHeader_cancelButton");
     await closeButton.click();
     session.log.done();
-};
+}
 
-module.exports.getE2EDeviceFromSettings = async function(session) {
+export async function getE2EDeviceFromSettings(session) {
     session.log.step(`gets e2e device/key from settings`);
     await openSettings(session, "security");
     const deviceAndKey = await session.queryAll(".mx_SettingsTab_section .mx_SecurityUserSettingsTab_deviceInfo code");
@@ -51,4 +52,4 @@ module.exports.getE2EDeviceFromSettings = async function(session) {
     await closeButton.click();
     session.log.done();
     return {id, key};
-};
+}
diff --git a/test/end-to-end-tests/src/usecases/timeline.js b/test/end-to-end-tests/src/usecases/timeline.js
index 3ff9e0f5b4..8a18e2653f 100644
--- a/test/end-to-end-tests/src/usecases/timeline.js
+++ b/test/end-to-end-tests/src/usecases/timeline.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-module.exports.scrollToTimelineTop = async function(session) {
+export async function scrollToTimelineTop(session) {
     session.log.step(`scrolls to the top of the timeline`);
     await session.page.evaluate(() => {
         return Promise.resolve().then(async () => {
@@ -40,9 +41,9 @@ module.exports.scrollToTimelineTop = async function(session) {
         });
     });
     session.log.done();
-};
+}
 
-module.exports.receiveMessage = async function(session, expectedMessage) {
+export async function receiveMessage(session, expectedMessage) {
     session.log.step(`receives message "${expectedMessage.body}" from ${expectedMessage.sender}`);
     // wait for a response to come in that contains the message
     // crude, but effective
@@ -66,10 +67,10 @@ module.exports.receiveMessage = async function(session, expectedMessage) {
     });
     assertMessage(lastMessage, expectedMessage);
     session.log.done();
-};
+}
 
 
-module.exports.checkTimelineContains = async function(session, expectedMessages, sendersDescription) {
+export async function checkTimelineContains(session, expectedMessages, sendersDescription) {
     session.log.step(`checks timeline contains ${expectedMessages.length} ` +
         `given messages${sendersDescription ? ` from ${sendersDescription}`:""}`);
     const eventTiles = await getAllEventTiles(session);
@@ -101,7 +102,7 @@ module.exports.checkTimelineContains = async function(session, expectedMessages,
     });
 
     session.log.done();
-};
+}
 
 function assertMessage(foundMessage, expectedMessage) {
     assert(foundMessage, `message ${JSON.stringify(expectedMessage)} not found in timeline`);
diff --git a/test/end-to-end-tests/src/usecases/verify.js b/test/end-to-end-tests/src/usecases/verify.js
index 11ff98d097..a8b71cfe5c 100644
--- a/test/end-to-end-tests/src/usecases/verify.js
+++ b/test/end-to-end-tests/src/usecases/verify.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2019 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -37,7 +38,7 @@ async function getSasCodes(session) {
     return sasLabels;
 }
 
-module.exports.startSasVerifcation = async function(session, name) {
+export async function startSasVerifcation(session, name) {
     await startVerification(session, name);
     // expect "Verify device" dialog and click "Begin Verification"
     await assertDialog(session, "Verify device");
@@ -50,9 +51,9 @@ module.exports.startSasVerifcation = async function(session, name) {
     // click "Got it" when verification is done
     await acceptDialog(session);
     return sasCodes;
-};
+}
 
-module.exports.acceptSasVerification = async function(session, name) {
+export async function acceptSasVerification(session, name) {
     await assertDialog(session, "Incoming Verification Request");
     const opponentLabelElement = await session.query(".mx_IncomingSasDialog_opponentProfile h2");
     const opponentLabel = await session.innerText(opponentLabelElement);
@@ -66,4 +67,4 @@ module.exports.acceptSasVerification = async function(session, name) {
     // click "Got it" when verification is done
     await acceptDialog(session);
     return sasCodes;
-};
+}
diff --git a/test/end-to-end-tests/src/util.js b/test/end-to-end-tests/src/util.js
index 699b11b5ce..cafe929eca 100644
--- a/test/end-to-end-tests/src/util.js
+++ b/test/end-to-end-tests/src/util.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2018 New Vector Ltd
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,14 +15,14 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-module.exports.range = function(start, amount, step = 1) {
+export function range(start, amount, step = 1) {
     const r = [];
     for (let i = 0; i < amount; ++i) {
         r.push(start + (i * step));
     }
     return r;
-};
+}
 
-module.exports.delay = function(ms) {
+export function delay(ms) {
     return new Promise((resolve) => setTimeout(resolve, ms));
-};
+}
diff --git a/test/mock-clock.js b/test/mock-clock.js
index 103e186c1f..7cad0e9483 100644
--- a/test/mock-clock.js
+++ b/test/mock-clock.js
@@ -1,5 +1,6 @@
 /*
 Copyright (c) 2008-2015 Pivotal Labs
+Copyright 2019 The Matrix.org Foundation C.I.C.
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -411,10 +412,10 @@ j$.MockDate = function() {
   return MockDate;
 }();
 
-const clock = new j$.Clock(global, function() { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
+const _clock = new j$.Clock(global, function() { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
 
-module.exports.clock = function() {
-    return clock;
-};
+export function clock() {
+    return _clock;
+}
 
 

From d56f0f2a25985f31df177c70ca87983bd921c0d6 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:19:56 -0700
Subject: [PATCH 33/86] Convert many imports to handle ES6 exports

Reliant upon https://github.com/matrix-org/matrix-react-sdk/pull/3761
---
 src/AddThreepid.js                                          | 2 +-
 src/Analytics.js                                            | 2 +-
 src/CallHandler.js                                          | 2 +-
 src/ContentMessages.js                                      | 2 +-
 src/CrossSigningManager.js                                  | 2 +-
 src/Entities.js                                             | 2 +-
 src/GroupAddressPicker.js                                   | 2 +-
 src/IdentityAuthClient.js                                   | 2 +-
 src/KeyRequestHandler.js                                    | 2 +-
 src/Lifecycle.js                                            | 2 +-
 src/MatrixClientPeg.js                                      | 2 +-
 src/Modal.js                                                | 2 +-
 src/Notifier.js                                             | 6 +++---
 src/Registration.js                                         | 2 +-
 src/RoomInvite.js                                           | 2 +-
 src/SlashCommands.js                                        | 2 +-
 src/Terms.js                                                | 2 +-
 src/actions/RoomListActions.js                              | 2 +-
 src/async-components/views/dialogs/ExportE2eKeysDialog.js   | 2 +-
 src/async-components/views/dialogs/ImportE2eKeysDialog.js   | 2 +-
 .../views/dialogs/keybackup/CreateKeyBackupDialog.js        | 2 +-
 .../views/dialogs/keybackup/IgnoreRecoveryReminderDialog.js | 2 +-
 .../views/dialogs/keybackup/NewRecoveryMethodDialog.js      | 2 +-
 .../views/dialogs/keybackup/RecoveryMethodRemovedDialog.js  | 2 +-
 .../dialogs/secretstorage/CreateSecretStorageDialog.js      | 2 +-
 src/autocomplete/CommunityProvider.js                       | 2 +-
 src/autocomplete/NotifProvider.js                           | 2 +-
 src/autocomplete/RoomProvider.js                            | 2 +-
 src/autocomplete/UserProvider.js                            | 2 +-
 src/components/structures/ContextMenu.js                    | 2 +-
 src/components/structures/CustomRoomTagPanel.js             | 2 +-
 src/components/structures/EmbeddedPage.js                   | 2 +-
 src/components/structures/FilePanel.js                      | 2 +-
 src/components/structures/GroupView.js                      | 2 +-
 src/components/structures/InteractiveAuth.js                | 2 +-
 src/components/structures/LeftPanel.js                      | 4 ++--
 src/components/structures/LoggedInView.js                   | 2 +-
 src/components/structures/MatrixChat.js                     | 2 +-
 src/components/structures/MessagePanel.js                   | 2 +-
 src/components/structures/MyGroups.js                       | 2 +-
 src/components/structures/RightPanel.js                     | 2 +-
 src/components/structures/RoomStatusBar.js                  | 2 +-
 src/components/structures/RoomSubList.js                    | 4 ++--
 src/components/structures/RoomView.js                       | 4 ++--
 src/components/structures/TabbedView.js                     | 2 +-
 src/components/structures/TagPanel.js                       | 2 +-
 src/components/structures/TagPanelButtons.js                | 2 +-
 src/components/structures/TimelinePanel.js                  | 2 +-
 src/components/structures/TopLeftMenuButton.js              | 2 +-
 src/components/structures/UserView.js                       | 2 +-
 src/components/structures/ViewSource.js                     | 2 +-
 src/components/structures/auth/ForgotPassword.js            | 2 +-
 src/components/structures/auth/Login.js                     | 2 +-
 src/components/structures/auth/PostRegistration.js          | 2 +-
 src/components/structures/auth/Registration.js              | 2 +-
 src/components/structures/auth/SoftLogout.js                | 2 +-
 src/components/views/auth/AuthHeader.js                     | 2 +-
 src/components/views/auth/AuthPage.js                       | 2 +-
 src/components/views/auth/CountryDropdown.js                | 2 +-
 src/components/views/auth/InteractiveAuthEntryComponents.js | 2 +-
 src/components/views/auth/LanguageSelector.js               | 2 +-
 src/components/views/auth/ModularServerConfig.js            | 2 +-
 src/components/views/auth/PasswordLogin.js                  | 2 +-
 src/components/views/auth/RegistrationForm.js               | 4 ++--
 src/components/views/auth/ServerConfig.js                   | 2 +-
 src/components/views/auth/ServerTypeSelector.js             | 2 +-
 src/components/views/auth/SignInToText.js                   | 2 +-
 src/components/views/auth/Welcome.js                        | 2 +-
 src/components/views/avatars/BaseAvatar.js                  | 2 +-
 src/components/views/avatars/GroupAvatar.js                 | 2 +-
 src/components/views/avatars/MemberAvatar.js                | 2 +-
 src/components/views/avatars/RoomAvatar.js                  | 4 ++--
 .../views/context_menus/GroupInviteTileContextMenu.js       | 2 +-
 src/components/views/context_menus/MessageContextMenu.js    | 2 +-
 src/components/views/context_menus/RoomTileContextMenu.js   | 2 +-
 .../views/context_menus/StatusMessageContextMenu.js         | 2 +-
 src/components/views/context_menus/TagTileContextMenu.js    | 2 +-
 src/components/views/dialogs/AddressPickerDialog.js         | 2 +-
 src/components/views/dialogs/AskInviteAnywayDialog.js       | 2 +-
 src/components/views/dialogs/BugReportDialog.js             | 2 +-
 src/components/views/dialogs/ChangelogDialog.js             | 2 +-
 src/components/views/dialogs/ConfirmAndWaitRedactDialog.js  | 2 +-
 src/components/views/dialogs/ConfirmRedactDialog.js         | 2 +-
 src/components/views/dialogs/ConfirmUserActionDialog.js     | 2 +-
 src/components/views/dialogs/ConfirmWipeDeviceDialog.js     | 2 +-
 src/components/views/dialogs/CreateGroupDialog.js           | 2 +-
 src/components/views/dialogs/CreateRoomDialog.js            | 2 +-
 src/components/views/dialogs/CryptoStoreTooNewDialog.js     | 2 +-
 src/components/views/dialogs/DeactivateAccountDialog.js     | 2 +-
 src/components/views/dialogs/DeviceVerifyDialog.js          | 2 +-
 src/components/views/dialogs/DevtoolsDialog.js              | 2 +-
 src/components/views/dialogs/ErrorDialog.js                 | 2 +-
 src/components/views/dialogs/IncomingSasDialog.js           | 2 +-
 src/components/views/dialogs/InfoDialog.js                  | 2 +-
 src/components/views/dialogs/IntegrationsDisabledDialog.js  | 2 +-
 .../views/dialogs/IntegrationsImpossibleDialog.js           | 2 +-
 src/components/views/dialogs/InteractiveAuthDialog.js       | 2 +-
 src/components/views/dialogs/KeyShareDialog.js              | 2 +-
 src/components/views/dialogs/LogoutDialog.js                | 2 +-
 src/components/views/dialogs/MessageEditHistoryDialog.js    | 2 +-
 src/components/views/dialogs/QuestionDialog.js              | 2 +-
 src/components/views/dialogs/ReportEventDialog.js           | 2 +-
 src/components/views/dialogs/RoomSettingsDialog.js          | 2 +-
 src/components/views/dialogs/RoomUpgradeDialog.js           | 2 +-
 src/components/views/dialogs/RoomUpgradeWarningDialog.js    | 2 +-
 src/components/views/dialogs/SessionRestoreErrorDialog.js   | 2 +-
 src/components/views/dialogs/SetEmailDialog.js              | 4 ++--
 src/components/views/dialogs/SetMxIdDialog.js               | 2 +-
 src/components/views/dialogs/SetPasswordDialog.js           | 2 +-
 src/components/views/dialogs/ShareDialog.js                 | 2 +-
 src/components/views/dialogs/SlashCommandHelpDialog.js      | 2 +-
 src/components/views/dialogs/StorageEvictedDialog.js        | 2 +-
 .../views/dialogs/TabbedIntegrationManagerDialog.js         | 4 ++--
 src/components/views/dialogs/TermsDialog.js                 | 2 +-
 src/components/views/dialogs/TextInputDialog.js             | 2 +-
 src/components/views/dialogs/UnknownDeviceDialog.js         | 2 +-
 src/components/views/dialogs/UploadConfirmDialog.js         | 2 +-
 src/components/views/dialogs/UploadFailureDialog.js         | 2 +-
 src/components/views/dialogs/UserSettingsDialog.js          | 2 +-
 .../views/dialogs/WidgetOpenIDPermissionsDialog.js          | 2 +-
 .../views/dialogs/keybackup/RestoreKeyBackupDialog.js       | 2 +-
 .../dialogs/secretstorage/AccessSecretStorageDialog.js      | 2 +-
 src/components/views/elements/AccessibleTooltipButton.js    | 2 +-
 src/components/views/elements/ActionButton.js               | 2 +-
 src/components/views/elements/AddressSelector.js            | 2 +-
 src/components/views/elements/AddressTile.js                | 2 +-
 src/components/views/elements/AppPermission.js              | 2 +-
 src/components/views/elements/AppTile.js                    | 2 +-
 src/components/views/elements/CreateRoomButton.js           | 2 +-
 src/components/views/elements/DeviceVerifyButtons.js        | 2 +-
 src/components/views/elements/DirectorySearchBox.js         | 2 +-
 src/components/views/elements/EditableTextContainer.js      | 2 +-
 src/components/views/elements/ErrorBoundary.js              | 2 +-
 src/components/views/elements/Field.js                      | 2 +-
 src/components/views/elements/GroupsButton.js               | 2 +-
 src/components/views/elements/LanguageDropdown.js           | 2 +-
 src/components/views/elements/ManageIntegsButton.js         | 2 +-
 src/components/views/elements/MemberEventListSummary.js     | 2 +-
 src/components/views/elements/PersistentApp.js              | 2 +-
 src/components/views/elements/Pill.js                       | 2 +-
 src/components/views/elements/ReplyThread.js                | 2 +-
 src/components/views/elements/RoomAliasField.js             | 2 +-
 src/components/views/elements/RoomDirectoryButton.js        | 2 +-
 src/components/views/elements/StartChatButton.js            | 2 +-
 src/components/views/elements/TagTile.js                    | 2 +-
 src/components/views/elements/TextWithTooltip.js            | 2 +-
 src/components/views/elements/TooltipButton.js              | 2 +-
 src/components/views/emojipicker/Category.js                | 2 +-
 src/components/views/emojipicker/EmojiPicker.js             | 2 +-
 src/components/views/emojipicker/QuickReactions.js          | 2 +-
 src/components/views/globals/CookieBar.js                   | 2 +-
 src/components/views/globals/NewVersionBar.js               | 2 +-
 src/components/views/globals/PasswordNagBar.js              | 2 +-
 src/components/views/groups/GroupInviteTile.js              | 2 +-
 src/components/views/groups/GroupMemberInfo.js              | 2 +-
 src/components/views/groups/GroupMemberList.js              | 2 +-
 src/components/views/groups/GroupMemberTile.js              | 2 +-
 src/components/views/groups/GroupPublicityToggle.js         | 2 +-
 src/components/views/groups/GroupRoomInfo.js                | 2 +-
 src/components/views/groups/GroupRoomList.js                | 2 +-
 src/components/views/groups/GroupRoomTile.js                | 2 +-
 src/components/views/groups/GroupTile.js                    | 2 +-
 src/components/views/groups/GroupUserSettings.js            | 2 +-
 src/components/views/messages/EditHistoryMessage.js         | 2 +-
 src/components/views/messages/MFileBody.js                  | 2 +-
 src/components/views/messages/MImageBody.js                 | 2 +-
 src/components/views/messages/MKeyVerificationRequest.js    | 2 +-
 src/components/views/messages/MStickerBody.js               | 2 +-
 src/components/views/messages/MessageActionBar.js           | 2 +-
 src/components/views/messages/MessageEvent.js               | 2 +-
 src/components/views/messages/ReactionsRow.js               | 2 +-
 src/components/views/messages/ReactionsRowButton.js         | 2 +-
 src/components/views/messages/ReactionsRowButtonTooltip.js  | 2 +-
 src/components/views/messages/RoomAvatarEvent.js            | 2 +-
 src/components/views/messages/TextualBody.js                | 2 +-
 src/components/views/messages/TextualEvent.js               | 3 +--
 src/components/views/right_panel/UserInfo.js                | 4 ++--
 src/components/views/room_settings/RelatedGroupSettings.js  | 2 +-
 src/components/views/room_settings/UrlPreviewSettings.js    | 2 +-
 src/components/views/rooms/AppsDrawer.js                    | 4 ++--
 src/components/views/rooms/AuxPanel.js                      | 4 ++--
 src/components/views/rooms/BasicMessageComposer.js          | 2 +-
 src/components/views/rooms/EditMessageComposer.js           | 2 +-
 src/components/views/rooms/EntityTile.js                    | 2 +-
 src/components/views/rooms/EventTile.js                     | 5 ++---
 src/components/views/rooms/MemberDeviceInfo.js              | 2 +-
 src/components/views/rooms/MemberInfo.js                    | 4 ++--
 src/components/views/rooms/MessageComposer.js               | 2 +-
 src/components/views/rooms/MessageComposerFormatBar.js      | 2 +-
 src/components/views/rooms/MessageComposerInput.js          | 2 +-
 src/components/views/rooms/ReplyPreview.js                  | 2 +-
 src/components/views/rooms/RoomBreadcrumbs.js               | 2 +-
 src/components/views/rooms/RoomDetailList.js                | 2 +-
 src/components/views/rooms/RoomDetailRow.js                 | 2 +-
 src/components/views/rooms/RoomHeader.js                    | 2 +-
 src/components/views/rooms/RoomPreviewBar.js                | 2 +-
 src/components/views/rooms/RoomRecoveryReminder.js          | 2 +-
 src/components/views/rooms/RoomTile.js                      | 2 +-
 src/components/views/rooms/RoomTopicEditor.js               | 2 +-
 src/components/views/rooms/RoomUpgradeWarningBar.js         | 2 +-
 src/components/views/rooms/SearchResultTile.js              | 2 +-
 src/components/views/rooms/SearchableEntityList.js          | 2 +-
 src/components/views/rooms/SendMessageComposer.js           | 2 +-
 src/components/views/rooms/SimpleRoomHeader.js              | 2 +-
 src/components/views/rooms/SlateMessageComposer.js          | 2 +-
 src/components/views/rooms/Stickerpicker.js                 | 2 +-
 src/components/views/rooms/ThirdPartyMemberInfo.js          | 2 +-
 src/components/views/rooms/UserTile.js                      | 2 +-
 src/components/views/rooms/WhoIsTypingTile.js               | 2 +-
 src/components/views/settings/ChangeAvatar.js               | 2 +-
 src/components/views/settings/ChangeDisplayName.js          | 2 +-
 src/components/views/settings/CrossSigningPanel.js          | 2 +-
 src/components/views/settings/DevicesPanel.js               | 2 +-
 src/components/views/settings/DevicesPanelEntry.js          | 2 +-
 src/components/views/settings/IntegrationManager.js         | 2 +-
 src/components/views/settings/KeyBackupPanel.js             | 2 +-
 src/components/views/settings/Notifications.js              | 2 +-
 src/components/views/settings/SetIdServer.js                | 2 +-
 src/components/views/settings/SetIntegrationManager.js      | 2 +-
 src/components/views/settings/account/EmailAddresses.js     | 2 +-
 src/components/views/settings/account/PhoneNumbers.js       | 2 +-
 src/components/views/settings/discovery/EmailAddresses.js   | 2 +-
 src/components/views/settings/discovery/PhoneNumbers.js     | 2 +-
 .../views/settings/tabs/room/AdvancedRoomSettingsTab.js     | 2 +-
 .../views/settings/tabs/room/GeneralRoomSettingsTab.js      | 2 +-
 .../views/settings/tabs/room/RolesRoomSettingsTab.js        | 2 +-
 .../views/settings/tabs/room/SecurityRoomSettingsTab.js     | 2 +-
 .../views/settings/tabs/user/GeneralUserSettingsTab.js      | 2 +-
 .../views/settings/tabs/user/PreferencesUserSettingsTab.js  | 2 +-
 .../views/settings/tabs/user/SecurityUserSettingsTab.js     | 2 +-
 src/components/views/terms/InlineTermsAgreement.js          | 2 +-
 src/components/views/toasts/VerificationRequestToast.js     | 2 +-
 src/components/views/verification/VerificationCancelled.js  | 2 +-
 src/components/views/verification/VerificationComplete.js   | 2 +-
 src/components/views/verification/VerificationShowSas.js    | 2 +-
 src/components/views/voip/CallPreview.js                    | 2 +-
 src/components/views/voip/CallView.js                       | 2 +-
 src/components/views/voip/IncomingCallBox.js                | 2 +-
 src/components/views/voip/VideoView.js                      | 2 +-
 src/createRoom.js                                           | 2 +-
 src/cryptodevices.js                                        | 2 +-
 src/editor/parts.js                                         | 2 +-
 src/integrations/IntegrationManagerInstance.js              | 2 +-
 src/integrations/IntegrationManagers.js                     | 2 +-
 src/stores/RoomListStore.js                                 | 2 +-
 src/stores/RoomViewStore.js                                 | 2 +-
 src/utils/MultiInviter.js                                   | 2 +-
 src/utils/pillify.js                                        | 2 +-
 src/utils/replaceableComponent.ts                           | 2 +-
 249 files changed, 263 insertions(+), 265 deletions(-)

diff --git a/src/AddThreepid.js b/src/AddThreepid.js
index 694c2e124c..4d027e4cfb 100644
--- a/src/AddThreepid.js
+++ b/src/AddThreepid.js
@@ -17,7 +17,7 @@ limitations under the License.
 */
 
 import MatrixClientPeg from './MatrixClientPeg';
-import sdk from './index';
+import * as sdk from './index';
 import Modal from './Modal';
 import { _t } from './languageHandler';
 import IdentityAuthClient from './IdentityAuthClient';
diff --git a/src/Analytics.js b/src/Analytics.js
index 3e208ad6bd..75b547d3d7 100644
--- a/src/Analytics.js
+++ b/src/Analytics.js
@@ -18,7 +18,7 @@ import { getCurrentLanguage, _t, _td } from './languageHandler';
 import PlatformPeg from './PlatformPeg';
 import SdkConfig from './SdkConfig';
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 
 const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/;
 const hashVarRegex = /#\/(group|room|user)\/.*$/;
diff --git a/src/CallHandler.js b/src/CallHandler.js
index ecbf6c2c12..a5e6c34ab3 100644
--- a/src/CallHandler.js
+++ b/src/CallHandler.js
@@ -56,7 +56,7 @@ limitations under the License.
 import MatrixClientPeg from './MatrixClientPeg';
 import PlatformPeg from './PlatformPeg';
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import Matrix from 'matrix-js-sdk';
 import dis from './dispatcher';
diff --git a/src/ContentMessages.js b/src/ContentMessages.js
index 6908a6a18e..4b8b911cfa 100644
--- a/src/ContentMessages.js
+++ b/src/ContentMessages.js
@@ -20,7 +20,7 @@ limitations under the License.
 import extend from './extend';
 import dis from './dispatcher';
 import MatrixClientPeg from './MatrixClientPeg';
-import sdk from './index';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
 import RoomViewStore from './stores/RoomViewStore';
diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js
index ab0a22e4d5..9f7b9e97ce 100644
--- a/src/CrossSigningManager.js
+++ b/src/CrossSigningManager.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 import MatrixClientPeg from './MatrixClientPeg';
 import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase';
 import { decodeRecoveryKey } from 'matrix-js-sdk/lib/crypto/recoverykey';
diff --git a/src/Entities.js b/src/Entities.js
index 8be1da0db8..3135953744 100644
--- a/src/Entities.js
+++ b/src/Entities.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import sdk from './index';
+import * as sdk from './index';
 
 function isMatch(query, name, uid) {
     query = query.toLowerCase();
diff --git a/src/GroupAddressPicker.js b/src/GroupAddressPicker.js
index 793f5c9227..2d34af01eb 100644
--- a/src/GroupAddressPicker.js
+++ b/src/GroupAddressPicker.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import Modal from './Modal';
-import sdk from './';
+import * as sdk from './';
 import MultiInviter from './utils/MultiInviter';
 import { _t } from './languageHandler';
 import MatrixClientPeg from './MatrixClientPeg';
diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js
index c82c93e7a6..a501426865 100644
--- a/src/IdentityAuthClient.js
+++ b/src/IdentityAuthClient.js
@@ -18,7 +18,7 @@ import { createClient, SERVICE_TYPES } from 'matrix-js-sdk';
 
 import MatrixClientPeg from './MatrixClientPeg';
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
 import {
diff --git a/src/KeyRequestHandler.js b/src/KeyRequestHandler.js
index c3de7988b2..8101d24e6e 100644
--- a/src/KeyRequestHandler.js
+++ b/src/KeyRequestHandler.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import sdk from './index';
+import * as sdk from './index';
 import Modal from './Modal';
 
 export default class KeyRequestHandler {
diff --git a/src/Lifecycle.js b/src/Lifecycle.js
index b81b563129..9847c972f4 100644
--- a/src/Lifecycle.js
+++ b/src/Lifecycle.js
@@ -28,7 +28,7 @@ import Presence from './Presence';
 import dis from './dispatcher';
 import DMRoomMap from './utils/DMRoomMap';
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 import ActiveWidgetStore from './stores/ActiveWidgetStore';
 import PlatformPeg from "./PlatformPeg";
 import { sendLoginRequest } from "./Login";
diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 46debab731..974c5b6f51 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -22,7 +22,7 @@ import {MatrixClient, MemoryStore} from 'matrix-js-sdk';
 import utils from 'matrix-js-sdk/lib/utils';
 import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline';
 import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set';
-import sdk from './index';
+import * as sdk from './index';
 import createMatrixClient from './utils/createMatrixClient';
 import SettingsStore from './settings/SettingsStore';
 import MatrixActionCreators from './actions/MatrixActionCreators';
diff --git a/src/Modal.js b/src/Modal.js
index 4fc9fdcb02..29d3af2e74 100644
--- a/src/Modal.js
+++ b/src/Modal.js
@@ -20,7 +20,7 @@ import ReactDOM from 'react-dom';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import Analytics from './Analytics';
-import sdk from './index';
+import * as sdk from './index';
 import dis from './dispatcher';
 import { _t } from './languageHandler';
 import {defer} from "./utils/promise";
diff --git a/src/Notifier.js b/src/Notifier.js
index dd691d8ca7..73b1eae33c 100644
--- a/src/Notifier.js
+++ b/src/Notifier.js
@@ -18,11 +18,11 @@ limitations under the License.
 
 import MatrixClientPeg from './MatrixClientPeg';
 import PlatformPeg from './PlatformPeg';
-import TextForEvent from './TextForEvent';
+import * as TextForEvent from './TextForEvent';
 import Analytics from './Analytics';
-import Avatar from './Avatar';
+import * as Avatar from './Avatar';
 import dis from './dispatcher';
-import sdk from './index';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
 import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
diff --git a/src/Registration.js b/src/Registration.js
index 42e172ca0b..e76e7bc5bf 100644
--- a/src/Registration.js
+++ b/src/Registration.js
@@ -21,7 +21,7 @@ limitations under the License.
  */
 
 import dis from './dispatcher';
-import sdk from './index';
+import * as sdk from './index';
 import Modal from './Modal';
 import { _t } from './languageHandler';
 // import MatrixClientPeg from './MatrixClientPeg';
diff --git a/src/RoomInvite.js b/src/RoomInvite.js
index 48baad5d9f..80979da372 100644
--- a/src/RoomInvite.js
+++ b/src/RoomInvite.js
@@ -21,7 +21,7 @@ import MultiInviter from './utils/MultiInviter';
 import Modal from './Modal';
 import { getAddressType } from './UserAddress';
 import createRoom from './createRoom';
-import sdk from './';
+import * as sdk from './';
 import dis from './dispatcher';
 import DMRoomMap from './utils/DMRoomMap';
 import { _t } from './languageHandler';
diff --git a/src/SlashCommands.js b/src/SlashCommands.js
index a9c015fdaf..b9b7866643 100644
--- a/src/SlashCommands.js
+++ b/src/SlashCommands.js
@@ -20,7 +20,7 @@ limitations under the License.
 import React from 'react';
 import MatrixClientPeg from './MatrixClientPeg';
 import dis from './dispatcher';
-import sdk from './index';
+import * as sdk from './index';
 import {_t, _td} from './languageHandler';
 import Modal from './Modal';
 import MultiInviter from './utils/MultiInviter';
diff --git a/src/Terms.js b/src/Terms.js
index 14a7ccb65e..f6a4850446 100644
--- a/src/Terms.js
+++ b/src/Terms.js
@@ -17,7 +17,7 @@ limitations under the License.
 import classNames from 'classnames';
 
 import MatrixClientPeg from './MatrixClientPeg';
-import sdk from './';
+import * as sdk from './';
 import Modal from './Modal';
 
 export class TermsNotSignedError extends Error {}
diff --git a/src/actions/RoomListActions.js b/src/actions/RoomListActions.js
index e5911c4e32..854fa1b367 100644
--- a/src/actions/RoomListActions.js
+++ b/src/actions/RoomListActions.js
@@ -20,7 +20,7 @@ import RoomListStore from '../stores/RoomListStore';
 import Modal from '../Modal';
 import * as Rooms from '../Rooms';
 import { _t } from '../languageHandler';
-import sdk from '../index';
+import * as sdk from '../index';
 
 const RoomListActions = {};
 
diff --git a/src/async-components/views/dialogs/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/ExportE2eKeysDialog.js
index ba2e985889..481075d0fa 100644
--- a/src/async-components/views/dialogs/ExportE2eKeysDialog.js
+++ b/src/async-components/views/dialogs/ExportE2eKeysDialog.js
@@ -22,7 +22,7 @@ import { _t } from '../../../languageHandler';
 
 import { MatrixClient } from 'matrix-js-sdk';
 import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 const PHASE_EDIT = 1;
 const PHASE_EXPORTING = 2;
diff --git a/src/async-components/views/dialogs/ImportE2eKeysDialog.js b/src/async-components/views/dialogs/ImportE2eKeysDialog.js
index de9e819f5a..591c84f5d3 100644
--- a/src/async-components/views/dialogs/ImportE2eKeysDialog.js
+++ b/src/async-components/views/dialogs/ImportE2eKeysDialog.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 
 import { MatrixClient } from 'matrix-js-sdk';
 import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 function readFileAsArrayBuffer(file) {
diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
index 3fac00c1b3..3b34c2f7a0 100644
--- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
+++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import FileSaver from 'file-saver';
 
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import MatrixClientPeg from '../../../../MatrixClientPeg';
 import { scorePassword } from '../../../../utils/PasswordScorer';
 import { _t } from '../../../../languageHandler';
diff --git a/src/async-components/views/dialogs/keybackup/IgnoreRecoveryReminderDialog.js b/src/async-components/views/dialogs/keybackup/IgnoreRecoveryReminderDialog.js
index a9df3cca6e..b79911c66e 100644
--- a/src/async-components/views/dialogs/keybackup/IgnoreRecoveryReminderDialog.js
+++ b/src/async-components/views/dialogs/keybackup/IgnoreRecoveryReminderDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from "react";
 import PropTypes from "prop-types";
-import sdk from "../../../../index";
+import * as sdk from "../../../../index";
 import { _t } from "../../../../languageHandler";
 
 export default class IgnoreRecoveryReminderDialog extends React.PureComponent {
diff --git a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
index 28281af771..5382aba23b 100644
--- a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
+++ b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from "react";
 import PropTypes from "prop-types";
-import sdk from "../../../../index";
+import * as sdk from "../../../../index";
 import MatrixClientPeg from '../../../../MatrixClientPeg';
 import dis from "../../../../dispatcher";
 import { _t } from "../../../../languageHandler";
diff --git a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js
index 1975fbe6d6..2ca595fdc9 100644
--- a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js
+++ b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from "react";
 import PropTypes from "prop-types";
-import sdk from "../../../../index";
+import * as sdk from "../../../../index";
 import dis from "../../../../dispatcher";
 import { _t } from "../../../../languageHandler";
 import Modal from "../../../../Modal";
diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
index 78ff2a1698..beb7a22157 100644
--- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
+++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import MatrixClientPeg from '../../../../MatrixClientPeg';
 import { scorePassword } from '../../../../utils/PasswordScorer';
 import FileSaver from 'file-saver';
diff --git a/src/autocomplete/CommunityProvider.js b/src/autocomplete/CommunityProvider.js
index 0acfd426fb..dce1d279ff 100644
--- a/src/autocomplete/CommunityProvider.js
+++ b/src/autocomplete/CommunityProvider.js
@@ -21,7 +21,7 @@ import AutocompleteProvider from './AutocompleteProvider';
 import MatrixClientPeg from '../MatrixClientPeg';
 import QueryMatcher from './QueryMatcher';
 import {PillCompletion} from './Components';
-import sdk from '../index';
+import * as sdk from '../index';
 import _sortBy from 'lodash/sortBy';
 import {makeGroupPermalink} from "../utils/permalinks/Permalinks";
 import type {Completion, SelectionRange} from "./Autocompleter";
diff --git a/src/autocomplete/NotifProvider.js b/src/autocomplete/NotifProvider.js
index 95cfb34616..1fb9da95c9 100644
--- a/src/autocomplete/NotifProvider.js
+++ b/src/autocomplete/NotifProvider.js
@@ -19,7 +19,7 @@ import AutocompleteProvider from './AutocompleteProvider';
 import { _t } from '../languageHandler';
 import MatrixClientPeg from '../MatrixClientPeg';
 import {PillCompletion} from './Components';
-import sdk from '../index';
+import * as sdk from '../index';
 import type {Completion, SelectionRange} from "./Autocompleter";
 
 const AT_ROOM_REGEX = /@\S*/g;
diff --git a/src/autocomplete/RoomProvider.js b/src/autocomplete/RoomProvider.js
index b67abc388e..91b4543432 100644
--- a/src/autocomplete/RoomProvider.js
+++ b/src/autocomplete/RoomProvider.js
@@ -24,7 +24,7 @@ import MatrixClientPeg from '../MatrixClientPeg';
 import QueryMatcher from './QueryMatcher';
 import {PillCompletion} from './Components';
 import {getDisplayAliasForRoom} from '../Rooms';
-import sdk from '../index';
+import * as sdk from '../index';
 import _sortBy from 'lodash/sortBy';
 import {makeRoomPermalink} from "../utils/permalinks/Permalinks";
 import type {Completion, SelectionRange} from "./Autocompleter";
diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js
index ac159c8213..3385e13b72 100644
--- a/src/autocomplete/UserProvider.js
+++ b/src/autocomplete/UserProvider.js
@@ -22,7 +22,7 @@ import React from 'react';
 import { _t } from '../languageHandler';
 import AutocompleteProvider from './AutocompleteProvider';
 import {PillCompletion} from './Components';
-import sdk from '../index';
+import * as sdk from '../index';
 import QueryMatcher from './QueryMatcher';
 import _sortBy from 'lodash/sortBy';
 import MatrixClientPeg from '../MatrixClientPeg';
diff --git a/src/components/structures/ContextMenu.js b/src/components/structures/ContextMenu.js
index e861e3d45f..bc6fd68686 100644
--- a/src/components/structures/ContextMenu.js
+++ b/src/components/structures/ContextMenu.js
@@ -21,7 +21,7 @@ import ReactDOM from 'react-dom';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import {Key} from "../../Keyboard";
-import sdk from "../../index";
+import * as sdk from "../../index";
 import AccessibleButton from "../views/elements/AccessibleButton";
 
 // Shamelessly ripped off Modal.js.  There's probably a better way
diff --git a/src/components/structures/CustomRoomTagPanel.js b/src/components/structures/CustomRoomTagPanel.js
index ee69d800ed..f378e0f25e 100644
--- a/src/components/structures/CustomRoomTagPanel.js
+++ b/src/components/structures/CustomRoomTagPanel.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import CustomRoomTagStore from '../../stores/CustomRoomTagStore';
 import AutoHideScrollbar from './AutoHideScrollbar';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import classNames from 'classnames';
 import * as FormattingUtils from '../../utils/FormattingUtils';
diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index ecc01a443d..8cc8a9424e 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -23,7 +23,7 @@ import PropTypes from 'prop-types';
 import request from 'browser-request';
 import { _t } from '../../languageHandler';
 import sanitizeHtml from 'sanitize-html';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import MatrixClientPeg from '../../MatrixClientPeg';
 import { MatrixClient } from 'matrix-js-sdk';
diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js
index f5a5912dd5..ef60f71ec9 100644
--- a/src/components/structures/FilePanel.js
+++ b/src/components/structures/FilePanel.js
@@ -19,7 +19,7 @@ import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 
 import Matrix from 'matrix-js-sdk';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import MatrixClientPeg from '../../MatrixClientPeg';
 import { _t } from '../../languageHandler';
 
diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js
index 9df4630136..07a9fbc521 100644
--- a/src/components/structures/GroupView.js
+++ b/src/components/structures/GroupView.js
@@ -20,7 +20,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../MatrixClientPeg';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import { getHostingLink } from '../../utils/HostingLink';
 import { sanitizedHtmlNode } from '../../HtmlUtils';
diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js
index 1981310a2f..e7194e9fa4 100644
--- a/src/components/structures/InteractiveAuth.js
+++ b/src/components/structures/InteractiveAuth.js
@@ -24,7 +24,7 @@ import PropTypes from 'prop-types';
 
 import {getEntryComponentForLoginType} from '../views/auth/InteractiveAuthEntryComponents';
 
-import sdk from '../../index';
+import * as sdk from '../../index';
 
 export default createReactClass({
     displayName: 'InteractiveAuth',
diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js
index a0ad2b5c81..080344abc6 100644
--- a/src/components/structures/LeftPanel.js
+++ b/src/components/structures/LeftPanel.js
@@ -21,9 +21,9 @@ import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import { MatrixClient } from 'matrix-js-sdk';
 import { Key } from '../../Keyboard';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
-import VectorConferenceHandler from '../../VectorConferenceHandler';
+import * as VectorConferenceHandler from '../../VectorConferenceHandler';
 import TagPanelButtons from './TagPanelButtons';
 import SettingsStore from '../../settings/SettingsStore';
 import {_t} from "../../languageHandler";
diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index df2eebd7c9..85b794f67f 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -26,7 +26,7 @@ import { Key, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
 import PageTypes from '../../PageTypes';
 import CallMediaHandler from '../../CallMediaHandler';
 import { fixupColorFonts } from '../../utils/FontManager';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import sessionStore from '../../stores/SessionStore';
 import MatrixClientPeg from '../../MatrixClientPeg';
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index 8105805ab0..1469324aaf 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -38,7 +38,7 @@ import Notifier from '../../Notifier';
 
 import Modal from "../../Modal";
 import Tinter from "../../Tinter";
-import sdk from '../../index';
+import * as sdk from '../../index';
 import { showStartChatInviteDialog, showRoomInviteDialog } from '../../RoomInvite';
 import * as Rooms from '../../Rooms';
 import linkifyMatrix from "../../linkify-matrix";
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index f7d22bc17a..01644d8aff 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import shouldHideEvent from '../../shouldHideEvent';
 import {wantsDateSeparator} from '../../DateUtils';
-import sdk from '../../index';
+import * as sdk from '../../index';
 
 import MatrixClientPeg from '../../MatrixClientPeg';
 import SettingsStore from '../../settings/SettingsStore';
diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js
index 63ae14ba09..3c01c3d6a3 100644
--- a/src/components/structures/MyGroups.js
+++ b/src/components/structures/MyGroups.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { MatrixClient } from 'matrix-js-sdk';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import { _t } from '../../languageHandler';
 import dis from '../../dispatcher';
 import AccessibleButton from '../views/elements/AccessibleButton';
diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js
index 1745c9d7dc..bb62699ecf 100644
--- a/src/components/structures/RightPanel.js
+++ b/src/components/structures/RightPanel.js
@@ -21,7 +21,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import { MatrixClient } from 'matrix-js-sdk';
 import RateLimitedFunc from '../../ratelimitedfunc';
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index b0aa4cb59b..a10faa199a 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import Matrix from 'matrix-js-sdk';
 import { _t, _td } from '../../languageHandler';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import MatrixClientPeg from '../../MatrixClientPeg';
 import Resend from '../../Resend';
 import * as cryptodevices from '../../cryptodevices';
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 2fbd19c428..e16fee64a5 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -19,9 +19,9 @@ limitations under the License.
 
 import React, {createRef} from 'react';
 import classNames from 'classnames';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
-import Unread from '../../Unread';
+import * as Unread from '../../Unread';
 import * as RoomNotifs from '../../RoomNotifs';
 import * as FormattingUtils from '../../utils/FormattingUtils';
 import IndicatorScrollbar from './IndicatorScrollbar';
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 2f8d274866..fbbc8b56ba 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -35,12 +35,12 @@ import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
 import MatrixClientPeg from '../../MatrixClientPeg';
 import ContentMessages from '../../ContentMessages';
 import Modal from '../../Modal';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import CallHandler from '../../CallHandler';
 import dis from '../../dispatcher';
 import Tinter from '../../Tinter';
 import rate_limited_func from '../../ratelimitedfunc';
-import ObjectUtils from '../../ObjectUtils';
+import * as ObjectUtils from '../../ObjectUtils';
 import * as Rooms from '../../Rooms';
 import eventSearch from '../../Searching';
 
diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js
index 01c68fad62..ae5f9e3ee1 100644
--- a/src/components/structures/TabbedView.js
+++ b/src/components/structures/TabbedView.js
@@ -19,7 +19,7 @@ limitations under the License.
 import * as React from "react";
 import {_t} from '../../languageHandler';
 import PropTypes from "prop-types";
-import sdk from "../../index";
+import * as sdk from "../../index";
 
 /**
  * Represents a tab for the TabbedView.
diff --git a/src/components/structures/TagPanel.js b/src/components/structures/TagPanel.js
index a758092dc8..0724027e37 100644
--- a/src/components/structures/TagPanel.js
+++ b/src/components/structures/TagPanel.js
@@ -22,7 +22,7 @@ import TagOrderStore from '../../stores/TagOrderStore';
 
 import GroupActions from '../../actions/GroupActions';
 
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import { _t } from '../../languageHandler';
 
diff --git a/src/components/structures/TagPanelButtons.js b/src/components/structures/TagPanelButtons.js
index 7255e12307..93a596baa3 100644
--- a/src/components/structures/TagPanelButtons.js
+++ b/src/components/structures/TagPanelButtons.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../index';
+import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import Modal from '../../Modal';
 import { _t } from '../../languageHandler';
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 41283b5308..d8c2b96424 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -31,7 +31,7 @@ const sdk = require('../../index');
 import { _t } from '../../languageHandler';
 const MatrixClientPeg = require("../../MatrixClientPeg");
 const dis = require("../../dispatcher");
-const ObjectUtils = require('../../ObjectUtils');
+import * as ObjectUtils from "../../ObjectUtils";
 const Modal = require("../../Modal");
 const UserActivity = require("../../UserActivity");
 import { KeyCode } from '../../Keyboard';
diff --git a/src/components/structures/TopLeftMenuButton.js b/src/components/structures/TopLeftMenuButton.js
index e7928ab4d7..0d7af81a07 100644
--- a/src/components/structures/TopLeftMenuButton.js
+++ b/src/components/structures/TopLeftMenuButton.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import {TopLeftMenu} from '../views/context_menus/TopLeftMenu';
 import BaseAvatar from '../views/avatars/BaseAvatar';
 import MatrixClientPeg from '../../MatrixClientPeg';
-import Avatar from '../../Avatar';
+import * as Avatar from '../../Avatar';
 import { _t } from '../../languageHandler';
 import dis from "../../dispatcher";
 import {ContextMenu, ContextMenuButton} from "./ContextMenu";
diff --git a/src/components/structures/UserView.js b/src/components/structures/UserView.js
index 26d0ff5044..57235093f7 100644
--- a/src/components/structures/UserView.js
+++ b/src/components/structures/UserView.js
@@ -19,7 +19,7 @@ import React from "react";
 import PropTypes from "prop-types";
 import Matrix from "matrix-js-sdk";
 import MatrixClientPeg from "../../MatrixClientPeg";
-import sdk from "../../index";
+import * as sdk from "../../index";
 import Modal from '../../Modal';
 import { _t } from '../../languageHandler';
 
diff --git a/src/components/structures/ViewSource.js b/src/components/structures/ViewSource.js
index ef4ede517a..391cbf6eef 100644
--- a/src/components/structures/ViewSource.js
+++ b/src/components/structures/ViewSource.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import SyntaxHighlight from '../views/elements/SyntaxHighlight';
 import {_t} from "../../languageHandler";
-import sdk from "../../index";
+import * as sdk from "../../index";
 
 
 module.exports = createReactClass({
diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js
index ada7d4449b..01453f1322 100644
--- a/src/components/structures/auth/ForgotPassword.js
+++ b/src/components/structures/auth/ForgotPassword.js
@@ -20,7 +20,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from "../../../Modal";
 import SdkConfig from "../../../SdkConfig";
 import PasswordReset from "../../../PasswordReset";
diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js
index ade417d156..bdc95d4b94 100644
--- a/src/components/structures/auth/Login.js
+++ b/src/components/structures/auth/Login.js
@@ -20,7 +20,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import {_t, _td} from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Login from '../../../Login';
 import SdkConfig from '../../../SdkConfig';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
diff --git a/src/components/structures/auth/PostRegistration.js b/src/components/structures/auth/PostRegistration.js
index a77b4d0d56..0395cb8d35 100644
--- a/src/components/structures/auth/PostRegistration.js
+++ b/src/components/structures/auth/PostRegistration.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import AuthPage from "../../views/auth/AuthPage";
diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js
index 69f34f764a..20769be4cd 100644
--- a/src/components/structures/auth/Registration.js
+++ b/src/components/structures/auth/Registration.js
@@ -21,7 +21,7 @@ import Matrix from 'matrix-js-sdk';
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t, _td } from '../../../languageHandler';
 import SdkConfig from '../../../SdkConfig';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js
index da19a852f6..bdc34117d0 100644
--- a/src/components/structures/auth/SoftLogout.js
+++ b/src/components/structures/auth/SoftLogout.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import * as Lifecycle from '../../../Lifecycle';
 import Modal from '../../../Modal';
diff --git a/src/components/views/auth/AuthHeader.js b/src/components/views/auth/AuthHeader.js
index 193f347857..abf9e8895e 100644
--- a/src/components/views/auth/AuthHeader.js
+++ b/src/components/views/auth/AuthHeader.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 module.exports = createReactClass({
     displayName: 'AuthHeader',
diff --git a/src/components/views/auth/AuthPage.js b/src/components/views/auth/AuthPage.js
index bfac6514e2..82f7270121 100644
--- a/src/components/views/auth/AuthPage.js
+++ b/src/components/views/auth/AuthPage.js
@@ -17,7 +17,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {replaceableComponent} from "../../../utils/replaceableComponent";
 
 @replaceableComponent("views.auth.AuthPage")
diff --git a/src/components/views/auth/CountryDropdown.js b/src/components/views/auth/CountryDropdown.js
index d8aa88c798..c55d2419ff 100644
--- a/src/components/views/auth/CountryDropdown.js
+++ b/src/components/views/auth/CountryDropdown.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 import { COUNTRIES } from '../../../phonenumber';
 import SdkConfig from "../../../SdkConfig";
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.js b/src/components/views/auth/InteractiveAuthEntryComponents.js
index dd661291f3..869e81c1f7 100644
--- a/src/components/views/auth/InteractiveAuthEntryComponents.js
+++ b/src/components/views/auth/InteractiveAuthEntryComponents.js
@@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
 import url from 'url';
 import classnames from 'classnames';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 
diff --git a/src/components/views/auth/LanguageSelector.js b/src/components/views/auth/LanguageSelector.js
index 32862478f4..99578d4504 100644
--- a/src/components/views/auth/LanguageSelector.js
+++ b/src/components/views/auth/LanguageSelector.js
@@ -18,7 +18,7 @@ import SdkConfig from "../../../SdkConfig";
 import {getCurrentLanguage} from "../../../languageHandler";
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import PlatformPeg from "../../../PlatformPeg";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import React from 'react';
 
 function onChange(newLang) {
diff --git a/src/components/views/auth/ModularServerConfig.js b/src/components/views/auth/ModularServerConfig.js
index 684e8d5912..32418d3462 100644
--- a/src/components/views/auth/ModularServerConfig.js
+++ b/src/components/views/auth/ModularServerConfig.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import SdkConfig from "../../../SdkConfig";
diff --git a/src/components/views/auth/PasswordLogin.js b/src/components/views/auth/PasswordLogin.js
index 63e77a938d..c836b96a89 100644
--- a/src/components/views/auth/PasswordLogin.js
+++ b/src/components/views/auth/PasswordLogin.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import SdkConfig from '../../../SdkConfig';
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js
index 03fb74462c..d85ad6b3b2 100644
--- a/src/components/views/auth/RegistrationForm.js
+++ b/src/components/views/auth/RegistrationForm.js
@@ -20,8 +20,8 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
-import Email from '../../../email';
+import * as sdk from '../../../index';
+import * as Email from '../../../email';
 import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/auth/ServerConfig.js b/src/components/views/auth/ServerConfig.js
index e5523b1e36..a86e27b6c2 100644
--- a/src/components/views/auth/ServerConfig.js
+++ b/src/components/views/auth/ServerConfig.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import AutoDiscoveryUtils from "../../../utils/AutoDiscoveryUtils";
diff --git a/src/components/views/auth/ServerTypeSelector.js b/src/components/views/auth/ServerTypeSelector.js
index ebc2ea6d37..341f81c546 100644
--- a/src/components/views/auth/ServerTypeSelector.js
+++ b/src/components/views/auth/ServerTypeSelector.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import classnames from 'classnames';
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import {makeType} from "../../../utils/TypeUtils";
diff --git a/src/components/views/auth/SignInToText.js b/src/components/views/auth/SignInToText.js
index a7acdc6705..7564096b7d 100644
--- a/src/components/views/auth/SignInToText.js
+++ b/src/components/views/auth/SignInToText.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import PropTypes from "prop-types";
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index a110631033..58f117ea36 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import AuthPage from "./AuthPage";
 
diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js
index 82db78615e..8218ffdfc6 100644
--- a/src/components/views/avatars/BaseAvatar.js
+++ b/src/components/views/avatars/BaseAvatar.js
@@ -20,7 +20,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { MatrixClient } from 'matrix-js-sdk';
-import AvatarLogic from '../../../Avatar';
+import * as AvatarLogic from '../../../Avatar';
 import SettingsStore from "../../../settings/SettingsStore";
 import AccessibleButton from '../elements/AccessibleButton';
 
diff --git a/src/components/views/avatars/GroupAvatar.js b/src/components/views/avatars/GroupAvatar.js
index e8ef2a5279..27122052dd 100644
--- a/src/components/views/avatars/GroupAvatar.js
+++ b/src/components/views/avatars/GroupAvatar.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 
 export default createReactClass({
diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js
index 383bab5e79..cb9ef70168 100644
--- a/src/components/views/avatars/MemberAvatar.js
+++ b/src/components/views/avatars/MemberAvatar.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-const Avatar = require('../../../Avatar');
+import * as Avatar from '../../../Avatar';
 const sdk = require("../../../index");
 const dispatcher = require("../../../dispatcher");
 
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index 6f8f236afc..d1e2ed25bb 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -19,8 +19,8 @@ import createReactClass from 'create-react-class';
 import {ContentRepo} from "matrix-js-sdk";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
-import sdk from "../../../index";
-import Avatar from '../../../Avatar';
+import * as sdk from "../../../index";
+import * as Avatar from '../../../Avatar';
 
 module.exports = createReactClass({
     displayName: 'RoomAvatar',
diff --git a/src/components/views/context_menus/GroupInviteTileContextMenu.js b/src/components/views/context_menus/GroupInviteTileContextMenu.js
index 3feffbc0d9..6d0f921ed0 100644
--- a/src/components/views/context_menus/GroupInviteTileContextMenu.js
+++ b/src/components/views/context_menus/GroupInviteTileContextMenu.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 import {Group} from 'matrix-js-sdk';
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index efbfc4322f..876e3b10ac 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -24,7 +24,7 @@ import {EventStatus} from 'matrix-js-sdk';
 
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 import Resend from '../../../Resend';
diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js
index f5e68bd20b..d9497d729e 100644
--- a/src/components/views/context_menus/RoomTileContextMenu.js
+++ b/src/components/views/context_menus/RoomTileContextMenu.js
@@ -21,7 +21,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t, _td } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
diff --git a/src/components/views/context_menus/StatusMessageContextMenu.js b/src/components/views/context_menus/StatusMessageContextMenu.js
index 441220c95e..e9dd42f123 100644
--- a/src/components/views/context_menus/StatusMessageContextMenu.js
+++ b/src/components/views/context_menus/StatusMessageContextMenu.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import AccessibleButton from '../elements/AccessibleButton';
 
 export default class StatusMessageContextMenu extends React.Component {
diff --git a/src/components/views/context_menus/TagTileContextMenu.js b/src/components/views/context_menus/TagTileContextMenu.js
index 1af0c9ae66..2be0487ced 100644
--- a/src/components/views/context_menus/TagTileContextMenu.js
+++ b/src/components/views/context_menus/TagTileContextMenu.js
@@ -21,7 +21,7 @@ import { MatrixClient } from 'matrix-js-sdk';
 import { _t } from '../../../languageHandler';
 import dis from '../../../dispatcher';
 import TagOrderActions from '../../../actions/TagOrderActions';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {MenuItem} from "../../structures/ContextMenu";
 
 export default class TagTileContextMenu extends React.Component {
diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js
index 2be505a798..a1cdb5d5bb 100644
--- a/src/components/views/dialogs/AddressPickerDialog.js
+++ b/src/components/views/dialogs/AddressPickerDialog.js
@@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 
 import { _t, _td } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import { addressTypes, getAddressType } from '../../../UserAddress.js';
diff --git a/src/components/views/dialogs/AskInviteAnywayDialog.js b/src/components/views/dialogs/AskInviteAnywayDialog.js
index 3d10752ff8..7fa6069478 100644
--- a/src/components/views/dialogs/AskInviteAnywayDialog.js
+++ b/src/components/views/dialogs/AskInviteAnywayDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {SettingLevel} from "../../../settings/SettingsStore";
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/dialogs/BugReportDialog.js b/src/components/views/dialogs/BugReportDialog.js
index a3c4ad96ee..9289947e61 100644
--- a/src/components/views/dialogs/BugReportDialog.js
+++ b/src/components/views/dialogs/BugReportDialog.js
@@ -19,7 +19,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/ChangelogDialog.js b/src/components/views/dialogs/ChangelogDialog.js
index 91f1af64e3..e58f56a639 100644
--- a/src/components/views/dialogs/ChangelogDialog.js
+++ b/src/components/views/dialogs/ChangelogDialog.js
@@ -17,7 +17,7 @@ Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import request from 'browser-request';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.js b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.js
index db00f445a8..0622dd7dfb 100644
--- a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.js
+++ b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 /*
diff --git a/src/components/views/dialogs/ConfirmRedactDialog.js b/src/components/views/dialogs/ConfirmRedactDialog.js
index c606706ed2..71139155ec 100644
--- a/src/components/views/dialogs/ConfirmRedactDialog.js
+++ b/src/components/views/dialogs/ConfirmRedactDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 /*
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.js b/src/components/views/dialogs/ConfirmUserActionDialog.js
index 4d33b2b500..14910fbf6d 100644
--- a/src/components/views/dialogs/ConfirmUserActionDialog.js
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.js
@@ -18,7 +18,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { MatrixClient } from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { GroupMemberType } from '../../../groups';
 
diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js
index b7ad5c2557..49b558976a 100644
--- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js
+++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export default class ConfirmWipeDeviceDialog extends React.Component {
     static propTypes = {
diff --git a/src/components/views/dialogs/CreateGroupDialog.js b/src/components/views/dialogs/CreateGroupDialog.js
index 3430a12e71..b88639ba5a 100644
--- a/src/components/views/dialogs/CreateGroupDialog.js
+++ b/src/components/views/dialogs/CreateGroupDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js
index 6a73d22708..cdc63b7f88 100644
--- a/src/components/views/dialogs/CreateRoomDialog.js
+++ b/src/components/views/dialogs/CreateRoomDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import withValidation from '../elements/Validation';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/CryptoStoreTooNewDialog.js b/src/components/views/dialogs/CryptoStoreTooNewDialog.js
index 0146420f46..11e202b0cc 100644
--- a/src/components/views/dialogs/CryptoStoreTooNewDialog.js
+++ b/src/components/views/dialogs/CryptoStoreTooNewDialog.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js
index 703ecaf092..bbf5dbe943 100644
--- a/src/components/views/dialogs/DeactivateAccountDialog.js
+++ b/src/components/views/dialogs/DeactivateAccountDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Analytics from '../../../Analytics';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import * as Lifecycle from '../../../Lifecycle';
diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js
index 0e191cc192..708dfb1dd6 100644
--- a/src/components/views/dialogs/DeviceVerifyDialog.js
+++ b/src/components/views/dialogs/DeviceVerifyDialog.js
@@ -20,7 +20,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
 import { _t } from '../../../languageHandler';
 import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js
index 9327e1e54e..dfb15f0e0c 100644
--- a/src/components/views/dialogs/DevtoolsDialog.js
+++ b/src/components/views/dialogs/DevtoolsDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SyntaxHighlight from '../elements/SyntaxHighlight';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
diff --git a/src/components/views/dialogs/ErrorDialog.js b/src/components/views/dialogs/ErrorDialog.js
index f6db0a14a5..15c87990d0 100644
--- a/src/components/views/dialogs/ErrorDialog.js
+++ b/src/components/views/dialogs/ErrorDialog.js
@@ -28,7 +28,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default createReactClass({
diff --git a/src/components/views/dialogs/IncomingSasDialog.js b/src/components/views/dialogs/IncomingSasDialog.js
index 0720fedddc..d0a184f543 100644
--- a/src/components/views/dialogs/IncomingSasDialog.js
+++ b/src/components/views/dialogs/IncomingSasDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 const PHASE_START = 0;
diff --git a/src/components/views/dialogs/InfoDialog.js b/src/components/views/dialogs/InfoDialog.js
index c54da480e6..8a8f51c25a 100644
--- a/src/components/views/dialogs/InfoDialog.js
+++ b/src/components/views/dialogs/InfoDialog.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import classNames from "classnames";
 
diff --git a/src/components/views/dialogs/IntegrationsDisabledDialog.js b/src/components/views/dialogs/IntegrationsDisabledDialog.js
index 3ab1123f8b..1ca638f0ab 100644
--- a/src/components/views/dialogs/IntegrationsDisabledDialog.js
+++ b/src/components/views/dialogs/IntegrationsDisabledDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import dis from '../../../dispatcher';
 
 export default class IntegrationsDisabledDialog extends React.Component {
diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.js
index 9927f627f1..f12e4232be 100644
--- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js
+++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export default class IntegrationsImpossibleDialog extends React.Component {
     static propTypes = {
diff --git a/src/components/views/dialogs/InteractiveAuthDialog.js b/src/components/views/dialogs/InteractiveAuthDialog.js
index 0b658bad81..ff9f55cb74 100644
--- a/src/components/views/dialogs/InteractiveAuthDialog.js
+++ b/src/components/views/dialogs/InteractiveAuthDialog.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 import AccessibleButton from '../elements/AccessibleButton';
diff --git a/src/components/views/dialogs/KeyShareDialog.js b/src/components/views/dialogs/KeyShareDialog.js
index 01e3479bb1..f9407213da 100644
--- a/src/components/views/dialogs/KeyShareDialog.js
+++ b/src/components/views/dialogs/KeyShareDialog.js
@@ -18,7 +18,7 @@ import Modal from '../../../Modal';
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 import { _t, _td } from '../../../languageHandler';
 
diff --git a/src/components/views/dialogs/LogoutDialog.js b/src/components/views/dialogs/LogoutDialog.js
index 47d4153494..67d6574084 100644
--- a/src/components/views/dialogs/LogoutDialog.js
+++ b/src/components/views/dialogs/LogoutDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.js b/src/components/views/dialogs/MessageEditHistoryDialog.js
index b5e4daa1c1..24c5d3b682 100644
--- a/src/components/views/dialogs/MessageEditHistoryDialog.js
+++ b/src/components/views/dialogs/MessageEditHistoryDialog.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import { _t } from '../../../languageHandler';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import {wantsDateSeparator} from '../../../DateUtils';
 import SettingsStore from '../../../settings/SettingsStore';
 
diff --git a/src/components/views/dialogs/QuestionDialog.js b/src/components/views/dialogs/QuestionDialog.js
index 4d2a699898..b165bf79e2 100644
--- a/src/components/views/dialogs/QuestionDialog.js
+++ b/src/components/views/dialogs/QuestionDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default createReactClass({
diff --git a/src/components/views/dialogs/ReportEventDialog.js b/src/components/views/dialogs/ReportEventDialog.js
index 394e5ad47d..dd5afeb477 100644
--- a/src/components/views/dialogs/ReportEventDialog.js
+++ b/src/components/views/dialogs/ReportEventDialog.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React, {PureComponent} from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import PropTypes from "prop-types";
 import {MatrixEvent} from "matrix-js-sdk";
diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js
index 740dc4d2c2..06a3f1301b 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.js
+++ b/src/components/views/dialogs/RoomSettingsDialog.js
@@ -24,7 +24,7 @@ import RolesRoomSettingsTab from "../settings/tabs/room/RolesRoomSettingsTab";
 import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab";
 import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
 import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import dis from "../../../dispatcher";
 
diff --git a/src/components/views/dialogs/RoomUpgradeDialog.js b/src/components/views/dialogs/RoomUpgradeDialog.js
index 6900ac6fe8..d81958c5f0 100644
--- a/src/components/views/dialogs/RoomUpgradeDialog.js
+++ b/src/components/views/dialogs/RoomUpgradeDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/RoomUpgradeWarningDialog.js b/src/components/views/dialogs/RoomUpgradeWarningDialog.js
index 4c5a1abf7a..1ee1bec987 100644
--- a/src/components/views/dialogs/RoomUpgradeWarningDialog.js
+++ b/src/components/views/dialogs/RoomUpgradeWarningDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import Modal from "../../../Modal";
diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js
index b9f6e77222..935faf0cad 100644
--- a/src/components/views/dialogs/SessionRestoreErrorDialog.js
+++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/SetEmailDialog.js b/src/components/views/dialogs/SetEmailDialog.js
index b527abffc9..2e38d6a7c4 100644
--- a/src/components/views/dialogs/SetEmailDialog.js
+++ b/src/components/views/dialogs/SetEmailDialog.js
@@ -18,8 +18,8 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
-import Email from '../../../email';
+import * as sdk from '../../../index';
+import * as Email from '../../../email';
 import AddThreepid from '../../../AddThreepid';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js
index 0294c1c700..dffb98443d 100644
--- a/src/components/views/dialogs/SetMxIdDialog.js
+++ b/src/components/views/dialogs/SetMxIdDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import classnames from 'classnames';
 import { KeyCode } from '../../../Keyboard';
diff --git a/src/components/views/dialogs/SetPasswordDialog.js b/src/components/views/dialogs/SetPasswordDialog.js
index 0fe65aaca3..c8752afa6c 100644
--- a/src/components/views/dialogs/SetPasswordDialog.js
+++ b/src/components/views/dialogs/SetPasswordDialog.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 
diff --git a/src/components/views/dialogs/ShareDialog.js b/src/components/views/dialogs/ShareDialog.js
index f9e77101fc..842c7fc109 100644
--- a/src/components/views/dialogs/ShareDialog.js
+++ b/src/components/views/dialogs/ShareDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import {Room, User, Group, RoomMember, MatrixEvent} from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import QRCode from 'qrcode-react';
 import {RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
diff --git a/src/components/views/dialogs/SlashCommandHelpDialog.js b/src/components/views/dialogs/SlashCommandHelpDialog.js
index fc8cb46342..9e48a92ed1 100644
--- a/src/components/views/dialogs/SlashCommandHelpDialog.js
+++ b/src/components/views/dialogs/SlashCommandHelpDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import {_t} from "../../../languageHandler";
 import {CommandCategories, CommandMap} from "../../../SlashCommands";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export default ({onFinished}) => {
     const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js
index 22fa3ae3ab..a22f302807 100644
--- a/src/components/views/dialogs/StorageEvictedDialog.js
+++ b/src/components/views/dialogs/StorageEvictedDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js b/src/components/views/dialogs/TabbedIntegrationManagerDialog.js
index e86a46fb36..9f5c9f6a11 100644
--- a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js
+++ b/src/components/views/dialogs/TabbedIntegrationManagerDialog.js
@@ -18,10 +18,10 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
 import {Room} from "matrix-js-sdk";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {dialogTermsInteractionCallback, TermsNotSignedError} from "../../../Terms";
 import classNames from 'classnames';
-import ScalarMessaging from "../../../ScalarMessaging";
+import * as ScalarMessaging from "../../../ScalarMessaging";
 
 export default class TabbedIntegrationManagerDialog extends React.Component {
     static propTypes = {
diff --git a/src/components/views/dialogs/TermsDialog.js b/src/components/views/dialogs/TermsDialog.js
index ea090ef080..2d1e62e01a 100644
--- a/src/components/views/dialogs/TermsDialog.js
+++ b/src/components/views/dialogs/TermsDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import url from 'url';
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t, pickBestLanguage } from '../../../languageHandler';
 
 import Matrix from 'matrix-js-sdk';
diff --git a/src/components/views/dialogs/TextInputDialog.js b/src/components/views/dialogs/TextInputDialog.js
index a5421acaf5..0ffc072cc0 100644
--- a/src/components/views/dialogs/TextInputDialog.js
+++ b/src/components/views/dialogs/TextInputDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 export default createReactClass({
     displayName: 'TextInputDialog',
diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js
index e7522e971d..23e84bbe78 100644
--- a/src/components/views/dialogs/UnknownDeviceDialog.js
+++ b/src/components/views/dialogs/UnknownDeviceDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/dialogs/UploadConfirmDialog.js b/src/components/views/dialogs/UploadConfirmDialog.js
index 98c031e89b..28f2183eb0 100644
--- a/src/components/views/dialogs/UploadConfirmDialog.js
+++ b/src/components/views/dialogs/UploadConfirmDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import filesize from "filesize";
 
diff --git a/src/components/views/dialogs/UploadFailureDialog.js b/src/components/views/dialogs/UploadFailureDialog.js
index e264f1a3fb..4be1656f66 100644
--- a/src/components/views/dialogs/UploadFailureDialog.js
+++ b/src/components/views/dialogs/UploadFailureDialog.js
@@ -18,7 +18,7 @@ import filesize from 'filesize';
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import ContentMessages from '../../../ContentMessages';
 
diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js
index d3ab2b8722..a3f586cdea 100644
--- a/src/components/views/dialogs/UserSettingsDialog.js
+++ b/src/components/views/dialogs/UserSettingsDialog.js
@@ -28,7 +28,7 @@ import PreferencesUserSettingsTab from "../settings/tabs/user/PreferencesUserSet
 import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab";
 import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab";
 import FlairUserSettingsTab from "../settings/tabs/user/FlairUserSettingsTab";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import SdkConfig from "../../../SdkConfig";
 import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
 
diff --git a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js
index 62bd1d2521..162cb4736a 100644
--- a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js
+++ b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
 import WidgetUtils from "../../../utils/WidgetUtils";
 
diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
index 45168c381e..99dd118438 100644
--- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
+++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import MatrixClientPeg from '../../../../MatrixClientPeg';
 import Modal from '../../../../Modal';
 
diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
index d116ce505f..64bf54ce8a 100644
--- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
+++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from "prop-types";
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import MatrixClientPeg from '../../../../MatrixClientPeg';
 
 import { _t } from '../../../../languageHandler';
diff --git a/src/components/views/elements/AccessibleTooltipButton.js b/src/components/views/elements/AccessibleTooltipButton.js
index c824ea4025..401683160a 100644
--- a/src/components/views/elements/AccessibleTooltipButton.js
+++ b/src/components/views/elements/AccessibleTooltipButton.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import AccessibleButton from "./AccessibleButton";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export default class AccessibleTooltipButton extends React.PureComponent {
     static propTypes = {
diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js
index ea9a9bd876..d2277bd69a 100644
--- a/src/components/views/elements/ActionButton.js
+++ b/src/components/views/elements/ActionButton.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import AccessibleButton from './AccessibleButton';
 import dis from '../../../dispatcher';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Analytics from '../../../Analytics';
 
 export default createReactClass({
diff --git a/src/components/views/elements/AddressSelector.js b/src/components/views/elements/AddressSelector.js
index fad57890c4..febe0ff480 100644
--- a/src/components/views/elements/AddressSelector.js
+++ b/src/components/views/elements/AddressSelector.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import classNames from 'classnames';
 import { UserAddressType } from '../../../UserAddress';
 
diff --git a/src/components/views/elements/AddressTile.js b/src/components/views/elements/AddressTile.js
index 6d6ac20a5d..5ea6ca110c 100644
--- a/src/components/views/elements/AddressTile.js
+++ b/src/components/views/elements/AddressTile.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import { _t } from '../../../languageHandler';
 import { UserAddressType } from '../../../UserAddress.js';
diff --git a/src/components/views/elements/AppPermission.js b/src/components/views/elements/AppPermission.js
index 8dc58643bd..e08e008259 100644
--- a/src/components/views/elements/AppPermission.js
+++ b/src/components/views/elements/AppPermission.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import url from 'url';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import WidgetUtils from "../../../utils/WidgetUtils";
 import MatrixClientPeg from "../../../MatrixClientPeg";
diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js
index 9f75e5433b..05491cf4d8 100644
--- a/src/components/views/elements/AppTile.js
+++ b/src/components/views/elements/AppTile.js
@@ -25,7 +25,7 @@ import WidgetMessaging from '../../../WidgetMessaging';
 import AccessibleButton from './AccessibleButton';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import AppPermission from './AppPermission';
 import AppWarning from './AppWarning';
 import MessageSpinner from './MessageSpinner';
diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js
index da937be3e1..1410bdabdb 100644
--- a/src/components/views/elements/CreateRoomButton.js
+++ b/src/components/views/elements/CreateRoomButton.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/elements/DeviceVerifyButtons.js b/src/components/views/elements/DeviceVerifyButtons.js
index 15678b7d7a..6867406a03 100644
--- a/src/components/views/elements/DeviceVerifyButtons.js
+++ b/src/components/views/elements/DeviceVerifyButtons.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/elements/DirectorySearchBox.js b/src/components/views/elements/DirectorySearchBox.js
index 78a7cb7eba..5fe2f6dbc8 100644
--- a/src/components/views/elements/DirectorySearchBox.js
+++ b/src/components/views/elements/DirectorySearchBox.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import classnames from 'classnames';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default class DirectorySearchBox extends React.Component {
diff --git a/src/components/views/elements/EditableTextContainer.js b/src/components/views/elements/EditableTextContainer.js
index 5cba98470c..53b3a454d2 100644
--- a/src/components/views/elements/EditableTextContainer.js
+++ b/src/components/views/elements/EditableTextContainer.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 /**
  * A component which wraps an EditableText, with a spinner while updates take
diff --git a/src/components/views/elements/ErrorBoundary.js b/src/components/views/elements/ErrorBoundary.js
index e36464c4ef..12708863e5 100644
--- a/src/components/views/elements/ErrorBoundary.js
+++ b/src/components/views/elements/ErrorBoundary.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import PlatformPeg from '../../../PlatformPeg';
diff --git a/src/components/views/elements/Field.js b/src/components/views/elements/Field.js
index 0a737d963a..86f73b68e4 100644
--- a/src/components/views/elements/Field.js
+++ b/src/components/views/elements/Field.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { debounce } from 'lodash';
 
 // Invoke validation from user input (when typing, etc.) at most once every N ms.
diff --git a/src/components/views/elements/GroupsButton.js b/src/components/views/elements/GroupsButton.js
index 7b15e96424..dd1118aba0 100644
--- a/src/components/views/elements/GroupsButton.js
+++ b/src/components/views/elements/GroupsButton.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js
index 451c97d958..3ebde884bb 100644
--- a/src/components/views/elements/LanguageDropdown.js
+++ b/src/components/views/elements/LanguageDropdown.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import * as languageHandler from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 
diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js
index 3503d1713b..b631ddee73 100644
--- a/src/components/views/elements/ManageIntegsButton.js
+++ b/src/components/views/elements/ManageIntegsButton.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js
index ef80efaa68..c47e095e01 100644
--- a/src/components/views/elements/MemberEventListSummary.js
+++ b/src/components/views/elements/MemberEventListSummary.js
@@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
 import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import {MatrixEvent} from "matrix-js-sdk";
 
 module.exports = createReactClass({
diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js
index 19e4be6083..e0155d846b 100644
--- a/src/components/views/elements/PersistentApp.js
+++ b/src/components/views/elements/PersistentApp.js
@@ -19,7 +19,7 @@ import createReactClass from 'create-react-class';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
 import WidgetUtils from '../../../utils/WidgetUtils';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 
 module.exports = createReactClass({
diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js
index 12830488b1..b8c8f433f2 100644
--- a/src/components/views/elements/Pill.js
+++ b/src/components/views/elements/Pill.js
@@ -17,7 +17,7 @@ limitations under the License.
 */
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import classNames from 'classnames';
 import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk';
diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js
index 55fd028980..0b766807d5 100644
--- a/src/components/views/elements/ReplyThread.js
+++ b/src/components/views/elements/ReplyThread.js
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {_t} from '../../../languageHandler';
 import PropTypes from 'prop-types';
 import dis from '../../../dispatcher';
diff --git a/src/components/views/elements/RoomAliasField.js b/src/components/views/elements/RoomAliasField.js
index 03f4000e59..2f3ddcb929 100644
--- a/src/components/views/elements/RoomAliasField.js
+++ b/src/components/views/elements/RoomAliasField.js
@@ -16,7 +16,7 @@ limitations under the License.
 import { _t } from '../../../languageHandler';
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import withValidation from './Validation';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 
diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js
index 1498157ee4..d0bff4beeb 100644
--- a/src/components/views/elements/RoomDirectoryButton.js
+++ b/src/components/views/elements/RoomDirectoryButton.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js
index 2132d63940..f828f8ae4d 100644
--- a/src/components/views/elements/StartChatButton.js
+++ b/src/components/views/elements/StartChatButton.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js
index 767980f0a0..28930bbabe 100644
--- a/src/components/views/elements/TagTile.js
+++ b/src/components/views/elements/TagTile.js
@@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 import { MatrixClient } from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import {_t} from '../../../languageHandler';
 import { isOnlyCtrlOrCmdIgnoreShiftKeyEvent } from '../../../Keyboard';
diff --git a/src/components/views/elements/TextWithTooltip.js b/src/components/views/elements/TextWithTooltip.js
index f6cef47117..c46bc3bfbb 100644
--- a/src/components/views/elements/TextWithTooltip.js
+++ b/src/components/views/elements/TextWithTooltip.js
@@ -16,7 +16,7 @@
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 export default class TextWithTooltip extends React.Component {
     static propTypes = {
diff --git a/src/components/views/elements/TooltipButton.js b/src/components/views/elements/TooltipButton.js
index 0cabf776a4..7d50473469 100644
--- a/src/components/views/elements/TooltipButton.js
+++ b/src/components/views/elements/TooltipButton.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 module.exports = createReactClass({
     displayName: 'TooltipButton',
diff --git a/src/components/views/emojipicker/Category.js b/src/components/views/emojipicker/Category.js
index ba525b76e2..3c4352105e 100644
--- a/src/components/views/emojipicker/Category.js
+++ b/src/components/views/emojipicker/Category.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import { CATEGORY_HEADER_HEIGHT, EMOJI_HEIGHT, EMOJIS_PER_ROW } from "./EmojiPicker";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 const OVERFLOW_ROWS = 3;
 
diff --git a/src/components/views/emojipicker/EmojiPicker.js b/src/components/views/emojipicker/EmojiPicker.js
index 0ec11c2b38..060bcbae28 100644
--- a/src/components/views/emojipicker/EmojiPicker.js
+++ b/src/components/views/emojipicker/EmojiPicker.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import EMOJIBASE from 'emojibase-data/en/compact.json';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 import * as recent from './recent';
diff --git a/src/components/views/emojipicker/QuickReactions.js b/src/components/views/emojipicker/QuickReactions.js
index 8444fb2d9c..0ecdd127c2 100644
--- a/src/components/views/emojipicker/QuickReactions.js
+++ b/src/components/views/emojipicker/QuickReactions.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { findEmojiData } from '../../../HtmlUtils';
 
diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js
index 04226468d8..8774e4f1fa 100644
--- a/src/components/views/globals/CookieBar.js
+++ b/src/components/views/globals/CookieBar.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Analytics from '../../../Analytics';
 
 export default class CookieBar extends React.Component {
diff --git a/src/components/views/globals/NewVersionBar.js b/src/components/views/globals/NewVersionBar.js
index abb9334242..c1854ee9f5 100644
--- a/src/components/views/globals/NewVersionBar.js
+++ b/src/components/views/globals/NewVersionBar.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import PlatformPeg from '../../../PlatformPeg';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/globals/PasswordNagBar.js b/src/components/views/globals/PasswordNagBar.js
index 0a4996d0ce..74735ca5ea 100644
--- a/src/components/views/globals/PasswordNagBar.js
+++ b/src/components/views/globals/PasswordNagBar.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js
index a21b091145..68020c3228 100644
--- a/src/components/views/groups/GroupInviteTile.js
+++ b/src/components/views/groups/GroupInviteTile.js
@@ -20,7 +20,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { MatrixClient } from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import {_t} from '../../../languageHandler';
 import classNames from 'classnames';
diff --git a/src/components/views/groups/GroupMemberInfo.js b/src/components/views/groups/GroupMemberInfo.js
index 3dac90fc35..2dd98f8160 100644
--- a/src/components/views/groups/GroupMemberInfo.js
+++ b/src/components/views/groups/GroupMemberInfo.js
@@ -21,7 +21,7 @@ import createReactClass from 'create-react-class';
 import { MatrixClient } from 'matrix-js-sdk';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { GroupMemberType } from '../../../groups';
 import GroupStore from '../../../stores/GroupStore';
diff --git a/src/components/views/groups/GroupMemberList.js b/src/components/views/groups/GroupMemberList.js
index 3228a862ce..05af70b266 100644
--- a/src/components/views/groups/GroupMemberList.js
+++ b/src/components/views/groups/GroupMemberList.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import GroupStore from '../../../stores/GroupStore';
 import PropTypes from 'prop-types';
diff --git a/src/components/views/groups/GroupMemberTile.js b/src/components/views/groups/GroupMemberTile.js
index c4b41d23ce..c395b00daa 100644
--- a/src/components/views/groups/GroupMemberTile.js
+++ b/src/components/views/groups/GroupMemberTile.js
@@ -20,7 +20,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { MatrixClient } from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { GroupMemberType } from '../../../groups';
 
diff --git a/src/components/views/groups/GroupPublicityToggle.js b/src/components/views/groups/GroupPublicityToggle.js
index bacf54382a..b885542300 100644
--- a/src/components/views/groups/GroupPublicityToggle.js
+++ b/src/components/views/groups/GroupPublicityToggle.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import GroupStore from '../../../stores/GroupStore';
 import ToggleSwitch from "../elements/ToggleSwitch";
 
diff --git a/src/components/views/groups/GroupRoomInfo.js b/src/components/views/groups/GroupRoomInfo.js
index f9f7324e23..42d8d89c69 100644
--- a/src/components/views/groups/GroupRoomInfo.js
+++ b/src/components/views/groups/GroupRoomInfo.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import { MatrixClient } from 'matrix-js-sdk';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import GroupStore from '../../../stores/GroupStore';
 
diff --git a/src/components/views/groups/GroupRoomList.js b/src/components/views/groups/GroupRoomList.js
index d57d5e313f..5fd8c9f31d 100644
--- a/src/components/views/groups/GroupRoomList.js
+++ b/src/components/views/groups/GroupRoomList.js
@@ -16,7 +16,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import GroupStore from '../../../stores/GroupStore';
 import PropTypes from 'prop-types';
 import { showGroupAddRoomDialog } from '../../../GroupAddressPicker';
diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js
index ae325d4796..fdf7c932d1 100644
--- a/src/components/views/groups/GroupRoomTile.js
+++ b/src/components/views/groups/GroupRoomTile.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {MatrixClient} from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { GroupRoomType } from '../../../groups';
 
diff --git a/src/components/views/groups/GroupTile.js b/src/components/views/groups/GroupTile.js
index 3b64c10a1e..aacfab9516 100644
--- a/src/components/views/groups/GroupTile.js
+++ b/src/components/views/groups/GroupTile.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {MatrixClient} from 'matrix-js-sdk';
 import { Draggable, Droppable } from 'react-beautiful-dnd';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import FlairStore from '../../../stores/FlairStore';
 
diff --git a/src/components/views/groups/GroupUserSettings.js b/src/components/views/groups/GroupUserSettings.js
index 3cd5731b99..0f49043551 100644
--- a/src/components/views/groups/GroupUserSettings.js
+++ b/src/components/views/groups/GroupUserSettings.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { MatrixClient } from 'matrix-js-sdk';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/messages/EditHistoryMessage.js b/src/components/views/messages/EditHistoryMessage.js
index dfd4db49b3..d4fc926f03 100644
--- a/src/components/views/messages/EditHistoryMessage.js
+++ b/src/components/views/messages/EditHistoryMessage.js
@@ -22,7 +22,7 @@ import {formatTime} from '../../../DateUtils';
 import {MatrixEvent} from 'matrix-js-sdk';
 import {pillifyLinks} from '../../../utils/pillify';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import Modal from '../../../Modal';
 import classNames from 'classnames';
diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js
index 552b1108d2..cc95bae64b 100644
--- a/src/components/views/messages/MFileBody.js
+++ b/src/components/views/messages/MFileBody.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import filesize from 'filesize';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {decryptFile} from '../../../utils/DecryptFile';
 import Tinter from '../../../Tinter';
diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js
index 427056203d..74d103fb2b 100644
--- a/src/components/views/messages/MImageBody.js
+++ b/src/components/views/messages/MImageBody.js
@@ -22,7 +22,7 @@ import { MatrixClient } from 'matrix-js-sdk';
 
 import MFileBody from './MFileBody';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { decryptFile } from '../../../utils/DecryptFile';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js
index b2a1724fc6..6b71193b37 100644
--- a/src/components/views/messages/MKeyVerificationRequest.js
+++ b/src/components/views/messages/MKeyVerificationRequest.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from "../../../Modal";
 import { _t } from '../../../languageHandler';
 import KeyVerificationStateObserver, {getNameForEventRoom, userLabelForEventRoom}
diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js
index ed82d49576..9839080661 100644
--- a/src/components/views/messages/MStickerBody.js
+++ b/src/components/views/messages/MStickerBody.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import MImageBody from './MImageBody';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 export default class MStickerBody extends MImageBody {
     // Mostly empty to prevent default behaviour of MImageBody
diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js
index 81e806cf62..36d764f52f 100644
--- a/src/components/views/messages/MessageActionBar.js
+++ b/src/components/views/messages/MessageActionBar.js
@@ -20,7 +20,7 @@ import React, {useEffect} from 'react';
 import PropTypes from 'prop-types';
 
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
 import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js
index ba271f95b5..eae6b6f3e3 100644
--- a/src/components/views/messages/MessageEvent.js
+++ b/src/components/views/messages/MessageEvent.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SettingsStore from "../../../settings/SettingsStore";
 import {Mjolnir} from "../../../mjolnir/Mjolnir";
 
diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js
index 3a8cd24518..e8c5563c6b 100644
--- a/src/components/views/messages/ReactionsRow.js
+++ b/src/components/views/messages/ReactionsRow.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { isContentActionable } from '../../../utils/EventUtils';
 import MatrixClientPeg from '../../../MatrixClientPeg';
diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.js
index 89bd6e7938..22714e4fc7 100644
--- a/src/components/views/messages/ReactionsRowButton.js
+++ b/src/components/views/messages/ReactionsRowButton.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
 
diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.js b/src/components/views/messages/ReactionsRowButtonTooltip.js
index d7e1ef3488..2061a9ffc2 100644
--- a/src/components/views/messages/ReactionsRowButtonTooltip.js
+++ b/src/components/views/messages/ReactionsRowButtonTooltip.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { unicodeToShortcode } from '../../../HtmlUtils';
 import { _t } from '../../../languageHandler';
 import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js
index 513e104d12..c72190ad1c 100644
--- a/src/components/views/messages/RoomAvatarEvent.js
+++ b/src/components/views/messages/RoomAvatarEvent.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import AccessibleButton from '../elements/AccessibleButton';
 
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 6bf45d9193..a5697712ab 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -23,7 +23,7 @@ import createReactClass from 'create-react-class';
 import highlight from 'highlight.js';
 import * as HtmlUtils from '../../../HtmlUtils';
 import {formatDate} from '../../../DateUtils';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/messages/TextualEvent.js b/src/components/views/messages/TextualEvent.js
index be9adeed77..ed63419029 100644
--- a/src/components/views/messages/TextualEvent.js
+++ b/src/components/views/messages/TextualEvent.js
@@ -17,8 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-
-const TextForEvent = require('../../../TextForEvent');
+import * as TextForEvent from "../../../TextForEvent";
 
 module.exports = createReactClass({
     displayName: 'TextualEvent',
diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js
index af8b4616f8..8201cc6795 100644
--- a/src/components/views/right_panel/UserInfo.js
+++ b/src/components/views/right_panel/UserInfo.js
@@ -23,7 +23,7 @@ import classNames from 'classnames';
 import {Group, RoomMember, User} from 'matrix-js-sdk';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import createRoom from '../../../createRoom';
 import DMRoomMap from '../../../utils/DMRoomMap';
@@ -32,7 +32,7 @@ import SdkConfig from '../../../SdkConfig';
 import SettingsStore from "../../../settings/SettingsStore";
 import {EventTimeline} from "matrix-js-sdk";
 import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
-import * as RoomViewStore from "../../../stores/RoomViewStore";
+import RoomViewStore from "../../../stores/RoomViewStore";
 import MultiInviter from "../../../utils/MultiInviter";
 import GroupStore from "../../../stores/GroupStore";
 import MatrixClientPeg from "../../../MatrixClientPeg";
diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js
index c30f446f41..f1ecc2ef70 100644
--- a/src/components/views/room_settings/RelatedGroupSettings.js
+++ b/src/components/views/room_settings/RelatedGroupSettings.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {MatrixEvent, MatrixClient} from 'matrix-js-sdk';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 import ErrorDialog from "../dialogs/ErrorDialog";
diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js
index 7a8332cc9f..15a2d6ac63 100644
--- a/src/components/views/room_settings/UrlPreviewSettings.js
+++ b/src/components/views/room_settings/UrlPreviewSettings.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import { _t, _td } from '../../../languageHandler';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import dis from "../../../dispatcher";
diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js
index e53570dc5b..907d5bca50 100644
--- a/src/components/views/rooms/AppsDrawer.js
+++ b/src/components/views/rooms/AppsDrawer.js
@@ -22,8 +22,8 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
 import AppTile from '../elements/AppTile';
 import Modal from '../../../Modal';
 import dis from '../../../dispatcher';
-import sdk from '../../../index';
-import ScalarMessaging from '../../../ScalarMessaging';
+import * as sdk from '../../../index';
+import * as ScalarMessaging from '../../../ScalarMessaging';
 import { _t } from '../../../languageHandler';
 import WidgetUtils from '../../../utils/WidgetUtils';
 import WidgetEchoStore from "../../../stores/WidgetEchoStore";
diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js
index a83160ddbf..7add29af49 100644
--- a/src/components/views/rooms/AuxPanel.js
+++ b/src/components/views/rooms/AuxPanel.js
@@ -19,9 +19,9 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import MatrixClientPeg from "../../../MatrixClientPeg";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from "../../../dispatcher";
-import ObjectUtils from '../../../ObjectUtils';
+import * as ObjectUtils from '../../../ObjectUtils';
 import AppsDrawer from './AppsDrawer';
 import { _t } from '../../../languageHandler';
 import classNames from 'classnames';
diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js
index c7659e89fb..9638fbe230 100644
--- a/src/components/views/rooms/BasicMessageComposer.js
+++ b/src/components/views/rooms/BasicMessageComposer.js
@@ -37,7 +37,7 @@ import TypingStore from "../../../stores/TypingStore";
 import EMOJIBASE from 'emojibase-data/en/compact.json';
 import SettingsStore from "../../../settings/SettingsStore";
 import EMOTICON_REGEX from 'emojibase-regex/emoticon';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {Key} from "../../../Keyboard";
 
 const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js
index 34b2d92590..d2cd3cc4d3 100644
--- a/src/components/views/rooms/EditMessageComposer.js
+++ b/src/components/views/rooms/EditMessageComposer.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {_t} from '../../../languageHandler';
 import PropTypes from 'prop-types';
 import dis from '../../../dispatcher';
diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js
index 0193275ca0..57db1ac240 100644
--- a/src/components/views/rooms/EntityTile.js
+++ b/src/components/views/rooms/EntityTile.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import AccessibleButton from '../elements/AccessibleButton';
 import { _t } from '../../../languageHandler';
 import classNames from "classnames";
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 988482df7f..c3e6eb6ccb 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -24,10 +24,10 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 const classNames = require("classnames");
 import { _t, _td } from '../../../languageHandler';
+import * as TextForEvent from "../../../TextForEvent";
 const Modal = require('../../../Modal');
 
 const sdk = require('../../../index');
-const TextForEvent = require('../../../TextForEvent');
 
 import dis from '../../../dispatcher';
 import SettingsStore from "../../../settings/SettingsStore";
@@ -35,8 +35,7 @@ import {EventStatus, MatrixClient} from 'matrix-js-sdk';
 import {formatTime} from "../../../DateUtils";
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
-
-const ObjectUtils = require('../../../ObjectUtils');
+import * as ObjectUtils from "../../../ObjectUtils";
 
 const eventTileTypes = {
     'm.room.message': 'messages.MessageEvent',
diff --git a/src/components/views/rooms/MemberDeviceInfo.js b/src/components/views/rooms/MemberDeviceInfo.js
index ff88c6f6e6..4e2f6d4191 100644
--- a/src/components/views/rooms/MemberDeviceInfo.js
+++ b/src/components/views/rooms/MemberDeviceInfo.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import classNames from 'classnames';
 
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index 1a2c8e2212..f2656dddc5 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -34,11 +34,11 @@ import classNames from 'classnames';
 import { MatrixClient } from 'matrix-js-sdk';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import createRoom from '../../../createRoom';
 import DMRoomMap from '../../../utils/DMRoomMap';
-import Unread from '../../../Unread';
+import * as Unread from '../../../Unread';
 import { findReadReceiptFromUserId } from '../../../utils/Receipt';
 import AccessibleButton from '../elements/AccessibleButton';
 import RoomViewStore from '../../../stores/RoomViewStore';
diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js
index 580e3b0d81..ae346cbc70 100644
--- a/src/components/views/rooms/MessageComposer.js
+++ b/src/components/views/rooms/MessageComposer.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import CallHandler from '../../../CallHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import Stickerpicker from './Stickerpicker';
diff --git a/src/components/views/rooms/MessageComposerFormatBar.js b/src/components/views/rooms/MessageComposerFormatBar.js
index 95c896c6fc..79ae9f34e8 100644
--- a/src/components/views/rooms/MessageComposerFormatBar.js
+++ b/src/components/views/rooms/MessageComposerFormatBar.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import classNames from 'classnames';
 
 export default class MessageComposerFormatBar extends React.PureComponent {
diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index cc92f7c750..2510adde9f 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -35,7 +35,7 @@ import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
 import {processCommandInput} from '../../../SlashCommands';
 import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
 import Modal from '../../../Modal';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Analytics from '../../../Analytics';
 
diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js
index caf8feeea2..a0d56b1116 100644
--- a/src/components/views/rooms/ReplyPreview.js
+++ b/src/components/views/rooms/ReplyPreview.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import dis from '../../../dispatcher';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js
index 79e9f5c862..7611ff58ee 100644
--- a/src/components/views/rooms/RoomBreadcrumbs.js
+++ b/src/components/views/rooms/RoomBreadcrumbs.js
@@ -21,7 +21,7 @@ import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import AccessibleButton from '../elements/AccessibleButton';
 import RoomAvatar from '../avatars/RoomAvatar';
 import classNames from 'classnames';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import Analytics from "../../../Analytics";
 import * as RoomNotifs from '../../../RoomNotifs';
 import * as FormattingUtils from "../../../utils/FormattingUtils";
diff --git a/src/components/views/rooms/RoomDetailList.js b/src/components/views/rooms/RoomDetailList.js
index 19cd24b6e5..db7b86da4f 100644
--- a/src/components/views/rooms/RoomDetailList.js
+++ b/src/components/views/rooms/RoomDetailList.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import React from 'react';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/rooms/RoomDetailRow.js b/src/components/views/rooms/RoomDetailRow.js
index 26a4697337..b3a8b68b0d 100644
--- a/src/components/views/rooms/RoomDetailRow.js
+++ b/src/components/views/rooms/RoomDetailRow.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import React, {createRef} from 'react';
 import { _t } from '../../../languageHandler';
 import { linkifyElement } from '../../../HtmlUtils';
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index eaf2e733ca..9b15cffcf5 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -18,7 +18,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import Modal from "../../../Modal";
diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js
index a43a4df158..80b552ea24 100644
--- a/src/components/views/rooms/RoomPreviewBar.js
+++ b/src/components/views/rooms/RoomPreviewBar.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import classNames from 'classnames';
diff --git a/src/components/views/rooms/RoomRecoveryReminder.js b/src/components/views/rooms/RoomRecoveryReminder.js
index 6b7366bc4f..b45dd3a32c 100644
--- a/src/components/views/rooms/RoomRecoveryReminder.js
+++ b/src/components/views/rooms/RoomRecoveryReminder.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from "react";
 import PropTypes from "prop-types";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import { _t } from "../../../languageHandler";
 import Modal from "../../../Modal";
 import MatrixClientPeg from "../../../MatrixClientPeg";
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 817ada9706..0b8aae9d06 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -24,7 +24,7 @@ import classNames from 'classnames';
 import dis from '../../../dispatcher';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import DMRoomMap from '../../../utils/DMRoomMap';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import {ContextMenu, ContextMenuButton, toRightOf} from '../../structures/ContextMenu';
 import * as RoomNotifs from '../../../RoomNotifs';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
diff --git a/src/components/views/rooms/RoomTopicEditor.js b/src/components/views/rooms/RoomTopicEditor.js
index a7d11313ff..ed55b66a9a 100644
--- a/src/components/views/rooms/RoomTopicEditor.js
+++ b/src/components/views/rooms/RoomTopicEditor.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from "../../../languageHandler";
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.js b/src/components/views/rooms/RoomUpgradeWarningBar.js
index 58d959ddcc..f7e167b253 100644
--- a/src/components/views/rooms/RoomUpgradeWarningBar.js
+++ b/src/components/views/rooms/RoomUpgradeWarningBar.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js
index 19ed490683..084d4baffc 100644
--- a/src/components/views/rooms/SearchResultTile.js
+++ b/src/components/views/rooms/SearchResultTile.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 module.exports = createReactClass({
     displayName: 'SearchResult',
diff --git a/src/components/views/rooms/SearchableEntityList.js b/src/components/views/rooms/SearchableEntityList.js
index 024816c6fc..0bd21635ba 100644
--- a/src/components/views/rooms/SearchableEntityList.js
+++ b/src/components/views/rooms/SearchableEntityList.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 
 // A list capable of displaying entities which conform to the SearchableEntity
diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js
index af25155588..3b4f3122c0 100644
--- a/src/components/views/rooms/SendMessageComposer.js
+++ b/src/components/views/rooms/SendMessageComposer.js
@@ -35,7 +35,7 @@ import {parseEvent} from '../../../editor/deserialize';
 import {findEditableEvent} from '../../../utils/EventUtils';
 import SendHistoryManager from "../../../SendHistoryManager";
 import {processCommandInput} from '../../../SlashCommands';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import {_t, _td} from '../../../languageHandler';
 import ContentMessages from '../../../ContentMessages';
diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js
index e1ade691d2..f22d9fc1d0 100644
--- a/src/components/views/rooms/SimpleRoomHeader.js
+++ b/src/components/views/rooms/SimpleRoomHeader.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import AccessibleButton from '../elements/AccessibleButton';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 // cancel button which is shared between room header and simple room header
diff --git a/src/components/views/rooms/SlateMessageComposer.js b/src/components/views/rooms/SlateMessageComposer.js
index ebd9017d73..7714676565 100644
--- a/src/components/views/rooms/SlateMessageComposer.js
+++ b/src/components/views/rooms/SlateMessageComposer.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import { _t, _td } from '../../../languageHandler';
 import CallHandler from '../../../CallHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js
index 24f256e706..f1f1113836 100644
--- a/src/components/views/rooms/Stickerpicker.js
+++ b/src/components/views/rooms/Stickerpicker.js
@@ -17,7 +17,7 @@ import React from 'react';
 import {_t, _td} from '../../../languageHandler';
 import AppTile from '../elements/AppTile';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import AccessibleButton from '../elements/AccessibleButton';
 import WidgetUtils from '../../../utils/WidgetUtils';
diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.js b/src/components/views/rooms/ThirdPartyMemberInfo.js
index db6ab479a3..991b20f583 100644
--- a/src/components/views/rooms/ThirdPartyMemberInfo.js
+++ b/src/components/views/rooms/ThirdPartyMemberInfo.js
@@ -20,7 +20,7 @@ import MatrixClientPeg from "../../../MatrixClientPeg";
 import {MatrixEvent} from "matrix-js-sdk";
 import {_t} from "../../../languageHandler";
 import dis from "../../../dispatcher";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import Modal from "../../../Modal";
 import {isValid3pidInvite} from "../../../RoomInvite";
 
diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js
index 76afda6dd7..006bd81c98 100644
--- a/src/components/views/rooms/UserTile.js
+++ b/src/components/views/rooms/UserTile.js
@@ -17,8 +17,8 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
+import * as Avatar from '../../../Avatar';
 
-const Avatar = require("../../../Avatar");
 const sdk = require('../../../index');
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/WhoIsTypingTile.js b/src/components/views/rooms/WhoIsTypingTile.js
index 0e23286eb6..03cc899977 100644
--- a/src/components/views/rooms/WhoIsTypingTile.js
+++ b/src/components/views/rooms/WhoIsTypingTile.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import WhoIsTyping from '../../../WhoIsTyping';
+import * as WhoIsTyping from '../../../WhoIsTyping';
 import Timer from '../../../utils/Timer';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import MemberAvatar from '../avatars/MemberAvatar';
diff --git a/src/components/views/settings/ChangeAvatar.js b/src/components/views/settings/ChangeAvatar.js
index 904b17b15f..03147bc06c 100644
--- a/src/components/views/settings/ChangeAvatar.js
+++ b/src/components/views/settings/ChangeAvatar.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import MatrixClientPeg from "../../../MatrixClientPeg";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/settings/ChangeDisplayName.js b/src/components/views/settings/ChangeDisplayName.js
index 90c761ba3d..946fe606e5 100644
--- a/src/components/views/settings/ChangeDisplayName.js
+++ b/src/components/views/settings/ChangeDisplayName.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/settings/CrossSigningPanel.js b/src/components/views/settings/CrossSigningPanel.js
index ccab886f17..5c7f7a21fe 100644
--- a/src/components/views/settings/CrossSigningPanel.js
+++ b/src/components/views/settings/CrossSigningPanel.js
@@ -18,7 +18,7 @@ import React from 'react';
 
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { accessSecretStorage } from '../../../CrossSigningManager';
 
 export default class CrossSigningPanel extends React.PureComponent {
diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js
index cb5db10be4..2da0a969af 100644
--- a/src/components/views/settings/DevicesPanel.js
+++ b/src/components/views/settings/DevicesPanel.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
diff --git a/src/components/views/settings/DevicesPanelEntry.js b/src/components/views/settings/DevicesPanelEntry.js
index 98ba29471d..8702f1e553 100644
--- a/src/components/views/settings/DevicesPanelEntry.js
+++ b/src/components/views/settings/DevicesPanelEntry.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import {formatDate} from '../../../DateUtils';
diff --git a/src/components/views/settings/IntegrationManager.js b/src/components/views/settings/IntegrationManager.js
index 1ab17ca8a0..7d2bed8de0 100644
--- a/src/components/views/settings/IntegrationManager.js
+++ b/src/components/views/settings/IntegrationManager.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import dis from '../../../dispatcher';
 
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js
index 559b1e0ba1..13fc9850b7 100644
--- a/src/components/views/settings/KeyBackupPanel.js
+++ b/src/components/views/settings/KeyBackupPanel.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js
index 7345980bff..15899c850c 100644
--- a/src/components/views/settings/Notifications.js
+++ b/src/components/views/settings/Notifications.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import SettingsStore, {SettingLevel} from '../../../settings/SettingsStore';
diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.js
index a7a2e01c22..64a5ce751c 100644
--- a/src/components/views/settings/SetIdServer.js
+++ b/src/components/views/settings/SetIdServer.js
@@ -18,7 +18,7 @@ import url from 'url';
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
 import dis from "../../../dispatcher";
diff --git a/src/components/views/settings/SetIntegrationManager.js b/src/components/views/settings/SetIntegrationManager.js
index e205f02e6c..da2953482f 100644
--- a/src/components/views/settings/SetIntegrationManager.js
+++ b/src/components/views/settings/SetIntegrationManager.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import {_t} from "../../../languageHandler";
 import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 
 export default class SetIntegrationManager extends React.Component {
diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js
index 07f2a60c38..b41fe13805 100644
--- a/src/components/views/settings/account/EmailAddresses.js
+++ b/src/components/views/settings/account/EmailAddresses.js
@@ -23,7 +23,7 @@ import Field from "../../elements/Field";
 import AccessibleButton from "../../elements/AccessibleButton";
 import * as Email from "../../../../email";
 import AddThreepid from "../../../../AddThreepid";
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 
 /*
diff --git a/src/components/views/settings/account/PhoneNumbers.js b/src/components/views/settings/account/PhoneNumbers.js
index 55e95a9031..57aa5781b1 100644
--- a/src/components/views/settings/account/PhoneNumbers.js
+++ b/src/components/views/settings/account/PhoneNumbers.js
@@ -23,7 +23,7 @@ import Field from "../../elements/Field";
 import AccessibleButton from "../../elements/AccessibleButton";
 import AddThreepid from "../../../../AddThreepid";
 import CountryDropdown from "../../auth/CountryDropdown";
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 
 /*
diff --git a/src/components/views/settings/discovery/EmailAddresses.js b/src/components/views/settings/discovery/EmailAddresses.js
index cc3d2d0dad..567d2b4374 100644
--- a/src/components/views/settings/discovery/EmailAddresses.js
+++ b/src/components/views/settings/discovery/EmailAddresses.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 
 import { _t } from "../../../../languageHandler";
 import MatrixClientPeg from "../../../../MatrixClientPeg";
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 import AddThreepid from '../../../../AddThreepid';
 
diff --git a/src/components/views/settings/discovery/PhoneNumbers.js b/src/components/views/settings/discovery/PhoneNumbers.js
index 4188d1cdc7..84ad7d61e7 100644
--- a/src/components/views/settings/discovery/PhoneNumbers.js
+++ b/src/components/views/settings/discovery/PhoneNumbers.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 
 import { _t } from "../../../../languageHandler";
 import MatrixClientPeg from "../../../../MatrixClientPeg";
-import sdk from '../../../../index';
+import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 import AddThreepid from '../../../../AddThreepid';
 
diff --git a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
index 101cd036e5..4fa3fb8649 100644
--- a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import MatrixClientPeg from "../../../../../MatrixClientPeg";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Modal from "../../../../../Modal";
 import dis from "../../../../../dispatcher";
diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
index 5d707fcf16..4423ef9ecb 100644
--- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
 import MatrixClientPeg from "../../../../../MatrixClientPeg";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import {MatrixClient} from "matrix-js-sdk";
 import dis from "../../../../../dispatcher";
diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
index c826f89916..0c53a13e96 100644
--- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t, _td} from "../../../../../languageHandler";
 import MatrixClientPeg from "../../../../../MatrixClientPeg";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Modal from "../../../../../Modal";
 
diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
index b44d7b019d..6dea081d96 100644
--- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import MatrixClientPeg from "../../../../../MatrixClientPeg";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
 import {SettingLevel} from "../../../../../settings/SettingsStore";
 import Modal from "../../../../../Modal";
diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
index cae4b19891..d4182a51d3 100644
--- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
@@ -30,7 +30,7 @@ import PropTypes from "prop-types";
 import {enumerateThemes, ThemeWatcher} from "../../../../../theme";
 import PlatformPeg from "../../../../../PlatformPeg";
 import MatrixClientPeg from "../../../../../MatrixClientPeg";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import Modal from "../../../../../Modal";
 import dis from "../../../../../dispatcher";
 import {Service, startTermsFlow} from "../../../../../Terms";
diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js
index 6fc854c155..f1d47b5756 100644
--- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js
@@ -21,7 +21,7 @@ import {SettingLevel} from "../../../../../settings/SettingsStore";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
 import SettingsStore from "../../../../../settings/SettingsStore";
 import Field from "../../../elements/Field";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import PlatformPeg from "../../../../../PlatformPeg";
 
 export default class PreferencesUserSettingsTab extends React.Component {
diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
index 98ec18df5a..8d0ec5bd69 100644
--- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
@@ -23,7 +23,7 @@ import * as FormattingUtils from "../../../../../utils/FormattingUtils";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Analytics from "../../../../../Analytics";
 import Modal from "../../../../../Modal";
-import sdk from "../../../../..";
+import * as sdk from "../../../../..";
 import {sleep} from "../../../../../utils/promise";
 
 export class IgnoredUser extends React.Component {
diff --git a/src/components/views/terms/InlineTermsAgreement.js b/src/components/views/terms/InlineTermsAgreement.js
index 836b34c585..75e8eccea3 100644
--- a/src/components/views/terms/InlineTermsAgreement.js
+++ b/src/components/views/terms/InlineTermsAgreement.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from "prop-types";
 import {_t, pickBestLanguage} from "../../../languageHandler";
-import sdk from "../../..";
+import * as sdk from "../../..";
 
 export default class InlineTermsAgreement extends React.Component {
     static propTypes = {
diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js
index 89af91c41f..bf64de665a 100644
--- a/src/components/views/toasts/VerificationRequestToast.js
+++ b/src/components/views/toasts/VerificationRequestToast.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 import Modal from "../../../Modal";
 import MatrixClientPeg from '../../../MatrixClientPeg';
diff --git a/src/components/views/verification/VerificationCancelled.js b/src/components/views/verification/VerificationCancelled.js
index baace2ca1e..fc2a287359 100644
--- a/src/components/views/verification/VerificationCancelled.js
+++ b/src/components/views/verification/VerificationCancelled.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default class VerificationCancelled extends React.Component {
diff --git a/src/components/views/verification/VerificationComplete.js b/src/components/views/verification/VerificationComplete.js
index 59f7ff924a..2214711b1f 100644
--- a/src/components/views/verification/VerificationComplete.js
+++ b/src/components/views/verification/VerificationComplete.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default class VerificationComplete extends React.Component {
diff --git a/src/components/views/verification/VerificationShowSas.js b/src/components/views/verification/VerificationShowSas.js
index e7846a0199..1e7785222f 100644
--- a/src/components/views/verification/VerificationShowSas.js
+++ b/src/components/views/verification/VerificationShowSas.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { _t, _td } from '../../../languageHandler';
 
 function capFirst(s) {
diff --git a/src/components/views/voip/CallPreview.js b/src/components/views/voip/CallPreview.js
index 15c30dcb5b..24bc29515a 100644
--- a/src/components/views/voip/CallPreview.js
+++ b/src/components/views/voip/CallPreview.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import CallHandler from '../../../CallHandler';
 import dis from '../../../dispatcher';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 module.exports = createReactClass({
     displayName: 'CallPreview',
diff --git a/src/components/views/voip/CallView.js b/src/components/views/voip/CallView.js
index 3a62ffbac2..e76fbf397f 100644
--- a/src/components/views/voip/CallView.js
+++ b/src/components/views/voip/CallView.js
@@ -18,7 +18,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import dis from '../../../dispatcher';
 import CallHandler from '../../../CallHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/voip/IncomingCallBox.js b/src/components/views/voip/IncomingCallBox.js
index 2a2839d103..a7ad7bfdf6 100644
--- a/src/components/views/voip/IncomingCallBox.js
+++ b/src/components/views/voip/IncomingCallBox.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 
 module.exports = createReactClass({
     displayName: 'IncomingCallBox',
diff --git a/src/components/views/voip/VideoView.js b/src/components/views/voip/VideoView.js
index 83584bcc68..fbb49ed367 100644
--- a/src/components/views/voip/VideoView.js
+++ b/src/components/views/voip/VideoView.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/createRoom.js b/src/createRoom.js
index 0ee90beba8..e0c4922f48 100644
--- a/src/createRoom.js
+++ b/src/createRoom.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import MatrixClientPeg from './MatrixClientPeg';
 import Modal from './Modal';
-import sdk from './index';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import dis from "./dispatcher";
 import * as Rooms from "./Rooms";
diff --git a/src/cryptodevices.js b/src/cryptodevices.js
index 161787fcbb..f56a80e1e4 100644
--- a/src/cryptodevices.js
+++ b/src/cryptodevices.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import Resend from './Resend';
-import sdk from './index';
+import * as sdk from './index';
 import dis from './dispatcher';
 import Modal from './Modal';
 import { _t } from './languageHandler';
diff --git a/src/editor/parts.js b/src/editor/parts.js
index f0b713beb6..137018d7e9 100644
--- a/src/editor/parts.js
+++ b/src/editor/parts.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 
 import AutocompleteWrapperModel from "./autocomplete";
-import Avatar from "../Avatar";
+import * as Avatar from "../Avatar";
 
 class BasePart {
     constructor(text = "") {
diff --git a/src/integrations/IntegrationManagerInstance.js b/src/integrations/IntegrationManagerInstance.js
index 4958209351..3ffe1e5401 100644
--- a/src/integrations/IntegrationManagerInstance.js
+++ b/src/integrations/IntegrationManagerInstance.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import ScalarAuthClient from "../ScalarAuthClient";
-import sdk from "../index";
+import * as sdk from "../index";
 import {dialogTermsInteractionCallback, TermsNotSignedError} from "../Terms";
 import type {Room} from "matrix-js-sdk";
 import Modal from '../Modal';
diff --git a/src/integrations/IntegrationManagers.js b/src/integrations/IntegrationManagers.js
index 6c4d2ae4d4..8400b3dc94 100644
--- a/src/integrations/IntegrationManagers.js
+++ b/src/integrations/IntegrationManagers.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import SdkConfig from '../SdkConfig';
-import sdk from "../index";
+import * as sdk from "../index";
 import Modal from '../Modal';
 import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
 import type {MatrixClient, MatrixEvent, Room} from "matrix-js-sdk";
diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js
index 134870398f..a0785cf10e 100644
--- a/src/stores/RoomListStore.js
+++ b/src/stores/RoomListStore.js
@@ -16,7 +16,7 @@ limitations under the License.
 import {Store} from 'flux/utils';
 import dis from '../dispatcher';
 import DMRoomMap from '../utils/DMRoomMap';
-import Unread from '../Unread';
+import * as Unread from '../Unread';
 import SettingsStore from "../settings/SettingsStore";
 
 /*
diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js
index a3caf876ef..8b25eba356 100644
--- a/src/stores/RoomViewStore.js
+++ b/src/stores/RoomViewStore.js
@@ -17,7 +17,7 @@ limitations under the License.
 import dis from '../dispatcher';
 import {Store} from 'flux/utils';
 import MatrixClientPeg from '../MatrixClientPeg';
-import sdk from '../index';
+import * as sdk from '../index';
 import Modal from '../Modal';
 import { _t } from '../languageHandler';
 import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache';
diff --git a/src/utils/MultiInviter.js b/src/utils/MultiInviter.js
index 887d829d76..2ea1da5bcc 100644
--- a/src/utils/MultiInviter.js
+++ b/src/utils/MultiInviter.js
@@ -19,7 +19,7 @@ import MatrixClientPeg from '../MatrixClientPeg';
 import {getAddressType} from '../UserAddress';
 import GroupStore from '../stores/GroupStore';
 import {_t} from "../languageHandler";
-import sdk from "../index";
+import * as sdk from "../index";
 import Modal from "../Modal";
 import SettingsStore from "../settings/SettingsStore";
 import {defer} from "./promise";
diff --git a/src/utils/pillify.js b/src/utils/pillify.js
index e943cfe657..524b0f75bb 100644
--- a/src/utils/pillify.js
+++ b/src/utils/pillify.js
@@ -18,7 +18,7 @@ import ReactDOM from 'react-dom';
 import MatrixClientPeg from '../MatrixClientPeg';
 import SettingsStore from "../settings/SettingsStore";
 import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
-import sdk from '../index';
+import * as sdk from '../index';
 
 export function pillifyLinks(nodes, mxEvent) {
     const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
diff --git a/src/utils/replaceableComponent.ts b/src/utils/replaceableComponent.ts
index 4777e2f395..9f617b27f3 100644
--- a/src/utils/replaceableComponent.ts
+++ b/src/utils/replaceableComponent.ts
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import sdk from '../index';
+import * as sdk from '../index';
 
 /**
  * Replaces a component with a skinned version if a skinned version exists.

From be4eeb5e07f79988ef540bc4373ec8ca2d692698 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:54:36 -0700
Subject: [PATCH 34/86] Fix js-sdk imports for new module

---
 src/MatrixClientPeg.js                              | 6 +++---
 src/RoomNotifs.js                                   | 2 +-
 src/settings/controllers/NotificationControllers.js | 2 +-
 src/utils/StorageManager.js                         | 2 +-
 src/utils/permalinks/Permalinks.js                  | 2 +-
 src/utils/pillify.js                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 974c5b6f51..f1713ca51f 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -19,9 +19,9 @@ limitations under the License.
 
 import {MatrixClient, MemoryStore} from 'matrix-js-sdk';
 
-import utils from 'matrix-js-sdk/lib/utils';
-import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline';
-import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set';
+import * as utils from 'matrix-js-sdk/lib/utils';
+import {EventTimeline} from 'matrix-js-sdk/lib/models/event-timeline';
+import {EventTimelineSet} from 'matrix-js-sdk/lib/models/event-timeline-set';
 import * as sdk from './index';
 import createMatrixClient from './utils/createMatrixClient';
 import SettingsStore from './settings/SettingsStore';
diff --git a/src/RoomNotifs.js b/src/RoomNotifs.js
index 5bef4afd25..9fe8bd75e4 100644
--- a/src/RoomNotifs.js
+++ b/src/RoomNotifs.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 
 import MatrixClientPeg from './MatrixClientPeg';
-import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
+import {PushProcessor} from 'matrix-js-sdk/lib/pushprocessor';
 
 export const ALL_MESSAGES_LOUD = 'all_messages_loud';
 export const ALL_MESSAGES = 'all_messages';
diff --git a/src/settings/controllers/NotificationControllers.js b/src/settings/controllers/NotificationControllers.js
index e78b67e847..0e24b4baac 100644
--- a/src/settings/controllers/NotificationControllers.js
+++ b/src/settings/controllers/NotificationControllers.js
@@ -18,7 +18,7 @@ import SettingController from "./SettingController";
 import MatrixClientPeg from '../../MatrixClientPeg';
 
 // XXX: This feels wrong.
-import PushProcessor from "matrix-js-sdk/lib/pushprocessor";
+import {PushProcessor} from "matrix-js-sdk/lib/pushprocessor";
 
 function isMasterRuleEnabled() {
     // Return the value of the master push rule as a default
diff --git a/src/utils/StorageManager.js b/src/utils/StorageManager.js
index 49a120a470..39466d66ce 100644
--- a/src/utils/StorageManager.js
+++ b/src/utils/StorageManager.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import Matrix from 'matrix-js-sdk';
-import LocalStorageCryptoStore from 'matrix-js-sdk/lib/crypto/store/localStorage-crypto-store';
+import {LocalStorageCryptoStore} from 'matrix-js-sdk/lib/crypto/store/localStorage-crypto-store';
 import Analytics from '../Analytics';
 
 const localStorage = window.localStorage;
diff --git a/src/utils/permalinks/Permalinks.js b/src/utils/permalinks/Permalinks.js
index aec7243236..25845f93a0 100644
--- a/src/utils/permalinks/Permalinks.js
+++ b/src/utils/permalinks/Permalinks.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import MatrixClientPeg from "../../MatrixClientPeg";
 import isIp from "is-ip";
-import utils from 'matrix-js-sdk/lib/utils';
+import * as utils from 'matrix-js-sdk/lib/utils';
 import SpecPermalinkConstructor, {baseUrl as matrixtoBaseUrl} from "./SpecPermalinkConstructor";
 import PermalinkConstructor, {PermalinkParts} from "./PermalinkConstructor";
 import RiotPermalinkConstructor from "./RiotPermalinkConstructor";
diff --git a/src/utils/pillify.js b/src/utils/pillify.js
index 524b0f75bb..d0675e4097 100644
--- a/src/utils/pillify.js
+++ b/src/utils/pillify.js
@@ -17,7 +17,7 @@ limitations under the License.
 import ReactDOM from 'react-dom';
 import MatrixClientPeg from '../MatrixClientPeg';
 import SettingsStore from "../settings/SettingsStore";
-import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
+import {PushProcessor} from 'matrix-js-sdk/lib/pushprocessor';
 import * as sdk from '../index';
 
 export function pillifyLinks(nodes, mxEvent) {

From 806d728d597c2d68a4f3d3307bd00b05b570146a Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 19:08:43 -0700
Subject: [PATCH 35/86] Import from the js-sdk's src/ directory

Because ES6 and such.
---
 src/CrossSigningManager.js                               | 4 ++--
 src/MatrixClientPeg.js                                   | 8 ++++----
 src/RoomNotifs.js                                        | 2 +-
 src/components/views/auth/ServerConfig.js                | 2 +-
 src/components/views/dialogs/DeviceVerifyDialog.js       | 2 +-
 src/components/views/messages/MKeyVerificationRequest.js | 2 +-
 src/components/views/rooms/MessageComposerInput.js       | 2 +-
 src/components/views/settings/KeyBackupPanel.js          | 2 +-
 src/components/views/toasts/VerificationRequestToast.js  | 2 +-
 src/settings/controllers/NotificationControllers.js      | 2 +-
 src/utils/StorageManager.js                              | 2 +-
 src/utils/permalinks/Permalinks.js                       | 2 +-
 src/utils/pillify.js                                     | 2 +-
 13 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js
index 9f7b9e97ce..a0919ddb28 100644
--- a/src/CrossSigningManager.js
+++ b/src/CrossSigningManager.js
@@ -17,8 +17,8 @@ limitations under the License.
 import Modal from './Modal';
 import * as sdk from './index';
 import MatrixClientPeg from './MatrixClientPeg';
-import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase';
-import { decodeRecoveryKey } from 'matrix-js-sdk/lib/crypto/recoverykey';
+import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
+import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
 import { _t } from './languageHandler';
 
 // This stores the secret storage private keys in memory for the JS SDK. This is
diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index f1713ca51f..44a05c2d6e 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -19,15 +19,15 @@ limitations under the License.
 
 import {MatrixClient, MemoryStore} from 'matrix-js-sdk';
 
-import * as utils from 'matrix-js-sdk/lib/utils';
-import {EventTimeline} from 'matrix-js-sdk/lib/models/event-timeline';
-import {EventTimelineSet} from 'matrix-js-sdk/lib/models/event-timeline-set';
+import * as utils from 'matrix-js-sdk/src/utils';
+import {EventTimeline} from 'matrix-js-sdk/src/models/event-timeline';
+import {EventTimelineSet} from 'matrix-js-sdk/src/models/event-timeline-set';
 import * as sdk from './index';
 import createMatrixClient from './utils/createMatrixClient';
 import SettingsStore from './settings/SettingsStore';
 import MatrixActionCreators from './actions/MatrixActionCreators';
 import Modal from './Modal';
-import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
+import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler";
 import * as StorageManager from './utils/StorageManager';
 import IdentityAuthClient from './IdentityAuthClient';
diff --git a/src/RoomNotifs.js b/src/RoomNotifs.js
index 9fe8bd75e4..efc647436b 100644
--- a/src/RoomNotifs.js
+++ b/src/RoomNotifs.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 
 import MatrixClientPeg from './MatrixClientPeg';
-import {PushProcessor} from 'matrix-js-sdk/lib/pushprocessor';
+import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
 
 export const ALL_MESSAGES_LOUD = 'all_messages_loud';
 export const ALL_MESSAGES = 'all_messages';
diff --git a/src/components/views/auth/ServerConfig.js b/src/components/views/auth/ServerConfig.js
index a86e27b6c2..5e17d50b55 100644
--- a/src/components/views/auth/ServerConfig.js
+++ b/src/components/views/auth/ServerConfig.js
@@ -24,7 +24,7 @@ import { _t } from '../../../languageHandler';
 import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import AutoDiscoveryUtils from "../../../utils/AutoDiscoveryUtils";
 import SdkConfig from "../../../SdkConfig";
-import { createClient } from 'matrix-js-sdk/lib/matrix';
+import { createClient } from 'matrix-js-sdk/src/matrix';
 import classNames from 'classnames';
 
 /*
diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js
index 708dfb1dd6..8cf5a8536e 100644
--- a/src/components/views/dialogs/DeviceVerifyDialog.js
+++ b/src/components/views/dialogs/DeviceVerifyDialog.js
@@ -23,7 +23,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
 import { _t } from '../../../languageHandler';
-import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
+import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import DMRoomMap from '../../../utils/DMRoomMap';
 import createRoom from "../../../createRoom";
 import dis from "../../../dispatcher";
diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js
index 6b71193b37..ca5b858f2f 100644
--- a/src/components/views/messages/MKeyVerificationRequest.js
+++ b/src/components/views/messages/MKeyVerificationRequest.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
+import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import * as sdk from '../../../index';
 import Modal from "../../../Modal";
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index 2510adde9f..c58fe677f5 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -31,7 +31,7 @@ import PlainWithPillsSerializer from "../../../autocomplete/PlainWithPillsSerial
 import classNames from 'classnames';
 
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
+import type {MatrixClient} from 'matrix-js-sdk/src/matrix';
 import {processCommandInput} from '../../../SlashCommands';
 import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
 import Modal from '../../../Modal';
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js
index 13fc9850b7..3eb9d5ac72 100644
--- a/src/components/views/settings/KeyBackupPanel.js
+++ b/src/components/views/settings/KeyBackupPanel.js
@@ -21,7 +21,7 @@ import * as sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
-import SettingsStore from '../../../../lib/settings/SettingsStore';
+import SettingsStore from '../../../../src/settings/SettingsStore';
 import { accessSecretStorage } from '../../../CrossSigningManager';
 
 export default class KeyBackupPanel extends React.PureComponent {
diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js
index bf64de665a..abc79c38d0 100644
--- a/src/components/views/toasts/VerificationRequestToast.js
+++ b/src/components/views/toasts/VerificationRequestToast.js
@@ -20,7 +20,7 @@ import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 import Modal from "../../../Modal";
 import MatrixClientPeg from '../../../MatrixClientPeg';
-import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
+import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import KeyVerificationStateObserver, {userLabelForEventRoom} from "../../../utils/KeyVerificationStateObserver";
 import dis from "../../../dispatcher";
 
diff --git a/src/settings/controllers/NotificationControllers.js b/src/settings/controllers/NotificationControllers.js
index 0e24b4baac..37d318eb1d 100644
--- a/src/settings/controllers/NotificationControllers.js
+++ b/src/settings/controllers/NotificationControllers.js
@@ -18,7 +18,7 @@ import SettingController from "./SettingController";
 import MatrixClientPeg from '../../MatrixClientPeg';
 
 // XXX: This feels wrong.
-import {PushProcessor} from "matrix-js-sdk/lib/pushprocessor";
+import {PushProcessor} from "matrix-js-sdk/src/pushprocessor";
 
 function isMasterRuleEnabled() {
     // Return the value of the master push rule as a default
diff --git a/src/utils/StorageManager.js b/src/utils/StorageManager.js
index 39466d66ce..c5a9f7aeed 100644
--- a/src/utils/StorageManager.js
+++ b/src/utils/StorageManager.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import Matrix from 'matrix-js-sdk';
-import {LocalStorageCryptoStore} from 'matrix-js-sdk/lib/crypto/store/localStorage-crypto-store';
+import {LocalStorageCryptoStore} from 'matrix-js-sdk/src/crypto/store/localStorage-crypto-store';
 import Analytics from '../Analytics';
 
 const localStorage = window.localStorage;
diff --git a/src/utils/permalinks/Permalinks.js b/src/utils/permalinks/Permalinks.js
index 25845f93a0..4b97d1664f 100644
--- a/src/utils/permalinks/Permalinks.js
+++ b/src/utils/permalinks/Permalinks.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import MatrixClientPeg from "../../MatrixClientPeg";
 import isIp from "is-ip";
-import * as utils from 'matrix-js-sdk/lib/utils';
+import * as utils from 'matrix-js-sdk/src/utils';
 import SpecPermalinkConstructor, {baseUrl as matrixtoBaseUrl} from "./SpecPermalinkConstructor";
 import PermalinkConstructor, {PermalinkParts} from "./PermalinkConstructor";
 import RiotPermalinkConstructor from "./RiotPermalinkConstructor";
diff --git a/src/utils/pillify.js b/src/utils/pillify.js
index d0675e4097..044b04181e 100644
--- a/src/utils/pillify.js
+++ b/src/utils/pillify.js
@@ -17,7 +17,7 @@ limitations under the License.
 import ReactDOM from 'react-dom';
 import MatrixClientPeg from '../MatrixClientPeg';
 import SettingsStore from "../settings/SettingsStore";
-import {PushProcessor} from 'matrix-js-sdk/lib/pushprocessor';
+import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
 import * as sdk from '../index';
 
 export function pillifyLinks(nodes, mxEvent) {

From 042bd35d79bb640b6f454194a1924f0175a8e665 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 14:13:46 -0700
Subject: [PATCH 36/86] Fix MatrixClientPeg imports

---
 src/AddThreepid.js                                           | 2 +-
 src/Avatar.js                                                | 2 +-
 src/CallHandler.js                                           | 2 +-
 src/ContentMessages.js                                       | 2 +-
 src/CrossSigningManager.js                                   | 2 +-
 src/FromWidgetPostMessageApi.js                              | 2 +-
 src/GroupAddressPicker.js                                    | 2 +-
 src/HtmlUtils.js                                             | 2 +-
 src/IdentityAuthClient.js                                    | 2 +-
 src/Lifecycle.js                                             | 2 +-
 src/MatrixClientPeg.js                                       | 5 -----
 src/Notifier.js                                              | 2 +-
 src/Presence.js                                              | 2 +-
 src/Registration.js                                          | 2 +-
 src/Resend.js                                                | 2 +-
 src/RoomInvite.js                                            | 2 +-
 src/RoomNotifs.js                                            | 2 +-
 src/Rooms.js                                                 | 2 +-
 src/ScalarAuthClient.js                                      | 3 +--
 src/ScalarMessaging.js                                       | 2 +-
 src/Searching.js                                             | 2 +-
 src/SlashCommands.js                                         | 2 +-
 src/Terms.js                                                 | 2 +-
 src/TextForEvent.js                                          | 2 +-
 src/Unread.js                                                | 2 +-
 src/VectorConferenceHandler.js                               | 2 +-
 src/WhoIsTyping.js                                           | 2 +-
 src/WidgetMessaging.js                                       | 2 +-
 src/async-components/views/dialogs/EncryptedEventDialog.js   | 3 ++-
 .../views/dialogs/keybackup/CreateKeyBackupDialog.js         | 2 +-
 .../views/dialogs/keybackup/NewRecoveryMethodDialog.js       | 2 +-
 .../views/dialogs/secretstorage/CreateSecretStorageDialog.js | 2 +-
 src/autocomplete/CommunityProvider.js                        | 2 +-
 src/autocomplete/NotifProvider.js                            | 2 +-
 src/autocomplete/RoomProvider.js                             | 2 +-
 src/autocomplete/UserProvider.js                             | 2 +-
 src/components/structures/EmbeddedPage.js                    | 2 +-
 src/components/structures/FilePanel.js                       | 2 +-
 src/components/structures/GroupView.js                       | 2 +-
 src/components/structures/LoggedInView.js                    | 2 +-
 src/components/structures/MatrixChat.js                      | 2 +-
 src/components/structures/MessagePanel.js                    | 2 +-
 src/components/structures/NotificationPanel.js               | 3 ++-
 src/components/structures/RoomDirectory.js                   | 4 ++--
 src/components/structures/RoomStatusBar.js                   | 2 +-
 src/components/structures/RoomView.js                        | 2 +-
 src/components/structures/TimelinePanel.js                   | 2 +-
 src/components/structures/TopLeftMenuButton.js               | 2 +-
 src/components/structures/UserView.js                        | 2 +-
 src/components/structures/auth/PostRegistration.js           | 2 +-
 src/components/structures/auth/Registration.js               | 2 +-
 src/components/structures/auth/SoftLogout.js                 | 2 +-
 src/components/views/avatars/GroupAvatar.js                  | 2 +-
 src/components/views/avatars/MemberStatusMessageAvatar.js    | 2 +-
 src/components/views/avatars/RoomAvatar.js                   | 2 +-
 src/components/views/context_menus/MessageContextMenu.js     | 2 +-
 src/components/views/context_menus/RoomTileContextMenu.js    | 2 +-
 .../views/context_menus/StatusMessageContextMenu.js          | 2 +-
 src/components/views/context_menus/TopLeftMenu.js            | 2 +-
 src/components/views/dialogs/AddressPickerDialog.js          | 2 +-
 src/components/views/dialogs/BaseDialog.js                   | 2 +-
 src/components/views/dialogs/CreateGroupDialog.js            | 2 +-
 src/components/views/dialogs/CreateRoomDialog.js             | 2 +-
 src/components/views/dialogs/DeactivateAccountDialog.js      | 2 +-
 src/components/views/dialogs/DeviceVerifyDialog.js           | 2 +-
 src/components/views/dialogs/DevtoolsDialog.js               | 2 +-
 src/components/views/dialogs/IncomingSasDialog.js            | 2 +-
 src/components/views/dialogs/LogoutDialog.js                 | 2 +-
 src/components/views/dialogs/MessageEditHistoryDialog.js     | 2 +-
 src/components/views/dialogs/ReportEventDialog.js            | 2 +-
 src/components/views/dialogs/RoomSettingsDialog.js           | 2 +-
 src/components/views/dialogs/RoomUpgradeDialog.js            | 2 +-
 src/components/views/dialogs/RoomUpgradeWarningDialog.js     | 2 +-
 src/components/views/dialogs/SetMxIdDialog.js                | 2 +-
 src/components/views/dialogs/UnknownDeviceDialog.js          | 2 +-
 .../views/dialogs/keybackup/RestoreKeyBackupDialog.js        | 2 +-
 .../views/dialogs/secretstorage/AccessSecretStorageDialog.js | 2 +-
 src/components/views/directory/NetworkDropdown.js            | 2 +-
 src/components/views/elements/AddressTile.js                 | 2 +-
 src/components/views/elements/AppPermission.js               | 2 +-
 src/components/views/elements/AppTile.js                     | 2 +-
 src/components/views/elements/DeviceVerifyButtons.js         | 2 +-
 src/components/views/elements/ErrorBoundary.js               | 2 +-
 src/components/views/elements/ImageView.js                   | 4 +---
 src/components/views/elements/PersistentApp.js               | 2 +-
 src/components/views/elements/Pill.js                        | 2 +-
 src/components/views/elements/RoomAliasField.js              | 2 +-
 src/components/views/emojipicker/ReactionPicker.js           | 2 +-
 src/components/views/groups/GroupInviteTile.js               | 2 +-
 src/components/views/messages/EditHistoryMessage.js          | 2 +-
 src/components/views/messages/MAudioBody.js                  | 2 +-
 src/components/views/messages/MFileBody.js                   | 2 +-
 src/components/views/messages/MKeyVerificationConclusion.js  | 2 +-
 src/components/views/messages/MKeyVerificationRequest.js     | 2 +-
 src/components/views/messages/MVideoBody.js                  | 2 +-
 src/components/views/messages/ReactionsRow.js                | 2 +-
 src/components/views/messages/ReactionsRowButton.js          | 2 +-
 src/components/views/messages/ReactionsRowButtonTooltip.js   | 2 +-
 src/components/views/messages/RoomAvatarEvent.js             | 2 +-
 src/components/views/messages/RoomCreate.js                  | 2 +-
 src/components/views/right_panel/UserInfo.js                 | 2 +-
 src/components/views/room_settings/AliasSettings.js          | 2 +-
 src/components/views/room_settings/RoomProfileSettings.js    | 2 +-
 src/components/views/room_settings/UrlPreviewSettings.js     | 2 +-
 src/components/views/rooms/AppsDrawer.js                     | 2 +-
 src/components/views/rooms/AuxPanel.js                       | 2 +-
 src/components/views/rooms/EventTile.js                      | 2 +-
 src/components/views/rooms/LinkPreviewWidget.js              | 2 +-
 src/components/views/rooms/MemberInfo.js                     | 2 +-
 src/components/views/rooms/MemberList.js                     | 2 +-
 src/components/views/rooms/MessageComposer.js                | 2 +-
 src/components/views/rooms/MessageComposerInput.js           | 2 +-
 src/components/views/rooms/PinnedEventTile.js                | 2 +-
 src/components/views/rooms/PinnedEventsPanel.js              | 2 +-
 src/components/views/rooms/RoomBreadcrumbs.js                | 2 +-
 src/components/views/rooms/RoomDetailRow.js                  | 2 +-
 src/components/views/rooms/RoomHeader.js                     | 2 +-
 src/components/views/rooms/RoomList.js                       | 2 +-
 src/components/views/rooms/RoomNameEditor.js                 | 2 +-
 src/components/views/rooms/RoomPreviewBar.js                 | 2 +-
 src/components/views/rooms/RoomRecoveryReminder.js           | 2 +-
 src/components/views/rooms/RoomTile.js                       | 2 +-
 src/components/views/rooms/RoomUpgradeWarningBar.js          | 2 +-
 src/components/views/rooms/SlateMessageComposer.js           | 2 +-
 src/components/views/rooms/Stickerpicker.js                  | 2 +-
 src/components/views/rooms/ThirdPartyMemberInfo.js           | 2 +-
 src/components/views/rooms/WhoIsTypingTile.js                | 2 +-
 src/components/views/settings/ChangeAvatar.js                | 2 +-
 src/components/views/settings/ChangeDisplayName.js           | 2 +-
 src/components/views/settings/ChangePassword.js              | 2 +-
 src/components/views/settings/CrossSigningPanel.js           | 2 +-
 src/components/views/settings/DevicesPanel.js                | 2 +-
 src/components/views/settings/DevicesPanelEntry.js           | 2 +-
 src/components/views/settings/KeyBackupPanel.js              | 2 +-
 src/components/views/settings/Notifications.js               | 2 +-
 src/components/views/settings/ProfileSettings.js             | 2 +-
 src/components/views/settings/SetIdServer.js                 | 2 +-
 src/components/views/settings/account/EmailAddresses.js      | 2 +-
 src/components/views/settings/account/PhoneNumbers.js        | 2 +-
 src/components/views/settings/discovery/EmailAddresses.js    | 2 +-
 src/components/views/settings/discovery/PhoneNumbers.js      | 2 +-
 .../views/settings/tabs/room/AdvancedRoomSettingsTab.js      | 2 +-
 .../views/settings/tabs/room/GeneralRoomSettingsTab.js       | 2 +-
 .../views/settings/tabs/room/NotificationSettingsTab.js      | 2 +-
 .../views/settings/tabs/room/RolesRoomSettingsTab.js         | 2 +-
 .../views/settings/tabs/room/SecurityRoomSettingsTab.js      | 2 +-
 .../views/settings/tabs/user/FlairUserSettingsTab.js         | 2 +-
 .../views/settings/tabs/user/GeneralUserSettingsTab.js       | 2 +-
 .../views/settings/tabs/user/HelpUserSettingsTab.js          | 2 +-
 .../views/settings/tabs/user/MjolnirUserSettingsTab.js       | 2 +-
 .../views/settings/tabs/user/SecurityUserSettingsTab.js      | 2 +-
 .../views/settings/tabs/user/VoiceUserSettingsTab.js         | 2 +-
 src/components/views/toasts/VerificationRequestToast.js      | 2 +-
 src/components/views/voip/CallView.js                        | 2 +-
 src/components/views/voip/IncomingCallBox.js                 | 2 +-
 src/createRoom.js                                            | 2 +-
 src/indexing/EventIndex.js                                   | 2 +-
 src/integrations/IntegrationManagers.js                      | 2 +-
 src/mjolnir/BanList.js                                       | 2 +-
 src/mjolnir/Mjolnir.js                                       | 2 +-
 src/rageshake/submit-rageshake.js                            | 2 +-
 src/settings/controllers/NotificationControllers.js          | 2 +-
 src/settings/handlers/AccountSettingsHandler.js              | 2 +-
 src/settings/handlers/DeviceSettingsHandler.js               | 2 +-
 src/settings/handlers/RoomAccountSettingsHandler.js          | 2 +-
 src/settings/handlers/RoomSettingsHandler.js                 | 2 +-
 src/stores/ActiveWidgetStore.js                              | 2 +-
 src/stores/GroupStore.js                                     | 2 +-
 src/stores/RoomViewStore.js                                  | 2 +-
 src/stores/TagOrderStore.js                                  | 2 +-
 src/stores/TypingStore.js                                    | 2 +-
 src/utils/DMRoomMap.js                                       | 2 +-
 src/utils/DecryptFile.js                                     | 2 +-
 src/utils/EventUtils.js                                      | 2 +-
 src/utils/HostingLink.js                                     | 2 +-
 src/utils/IdentityServerUtils.js                             | 2 +-
 src/utils/KeyVerificationStateObserver.js                    | 2 +-
 src/utils/MultiInviter.js                                    | 2 +-
 src/utils/PasswordScorer.js                                  | 2 +-
 src/utils/WidgetUtils.js                                     | 2 +-
 src/utils/permalinks/Permalinks.js                           | 2 +-
 src/utils/pillify.js                                         | 2 +-
 test/ScalarAuthClient-test.js                                | 2 +-
 test/Terms-test.js                                           | 2 +-
 test/components/structures/GroupView-test.js                 | 2 +-
 test/components/structures/MessagePanel-test.js              | 2 +-
 test/components/views/dialogs/InteractiveAuthDialog-test.js  | 2 +-
 test/components/views/groups/GroupMemberList-test.js         | 2 +-
 test/components/views/rooms/MemberList-test.js               | 2 +-
 test/components/views/rooms/MessageComposerInput-test.js     | 2 +-
 test/components/views/rooms/RoomList-test.js                 | 2 +-
 test/components/views/rooms/RoomSettings-test.js             | 2 +-
 192 files changed, 194 insertions(+), 200 deletions(-)

diff --git a/src/AddThreepid.js b/src/AddThreepid.js
index 4d027e4cfb..7a3250d0ca 100644
--- a/src/AddThreepid.js
+++ b/src/AddThreepid.js
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import * as sdk from './index';
 import Modal from './Modal';
 import { _t } from './languageHandler';
diff --git a/src/Avatar.js b/src/Avatar.js
index 17860698cb..c74f21bd37 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 'use strict';
 import {ContentRepo} from 'matrix-js-sdk';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import DMRoomMap from './utils/DMRoomMap';
 
 module.exports = {
diff --git a/src/CallHandler.js b/src/CallHandler.js
index a5e6c34ab3..2c22b12a3d 100644
--- a/src/CallHandler.js
+++ b/src/CallHandler.js
@@ -53,7 +53,7 @@ limitations under the License.
  * }
  */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import PlatformPeg from './PlatformPeg';
 import Modal from './Modal';
 import * as sdk from './index';
diff --git a/src/ContentMessages.js b/src/ContentMessages.js
index 4b8b911cfa..0752b0e59d 100644
--- a/src/ContentMessages.js
+++ b/src/ContentMessages.js
@@ -19,7 +19,7 @@ limitations under the License.
 
 import extend from './extend';
 import dis from './dispatcher';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js
index a0919ddb28..a242042bdb 100644
--- a/src/CrossSigningManager.js
+++ b/src/CrossSigningManager.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import Modal from './Modal';
 import * as sdk from './index';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
 import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
 import { _t } from './languageHandler';
diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js
index 8915c1412f..64caba0fdf 100644
--- a/src/FromWidgetPostMessageApi.js
+++ b/src/FromWidgetPostMessageApi.js
@@ -20,7 +20,7 @@ import URL from 'url';
 import dis from './dispatcher';
 import WidgetMessagingEndpoint from './WidgetMessagingEndpoint';
 import ActiveWidgetStore from './stores/ActiveWidgetStore';
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 import RoomViewStore from "./stores/RoomViewStore";
 import {IntegrationManagers} from "./integrations/IntegrationManagers";
 import SettingsStore from "./settings/SettingsStore";
diff --git a/src/GroupAddressPicker.js b/src/GroupAddressPicker.js
index 2d34af01eb..9131a89e5d 100644
--- a/src/GroupAddressPicker.js
+++ b/src/GroupAddressPicker.js
@@ -19,7 +19,7 @@ import Modal from './Modal';
 import * as sdk from './';
 import MultiInviter from './utils/MultiInviter';
 import { _t } from './languageHandler';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import GroupStore from './stores/GroupStore';
 import {allSettled} from "./utils/promise";
 
diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js
index 2b7384a5aa..3402ee13e3 100644
--- a/src/HtmlUtils.js
+++ b/src/HtmlUtils.js
@@ -29,7 +29,7 @@ import linkifyMatrix from './linkify-matrix';
 import _linkifyElement from 'linkifyjs/element';
 import _linkifyString from 'linkifyjs/string';
 import classNames from 'classnames';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import url from 'url';
 
 import EMOJIBASE from 'emojibase-data/en/compact.json';
diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js
index a501426865..72432b9a44 100644
--- a/src/IdentityAuthClient.js
+++ b/src/IdentityAuthClient.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import { createClient, SERVICE_TYPES } from 'matrix-js-sdk';
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import Modal from './Modal';
 import * as sdk from './index';
 import { _t } from './languageHandler';
diff --git a/src/Lifecycle.js b/src/Lifecycle.js
index 9847c972f4..0796e326a0 100644
--- a/src/Lifecycle.js
+++ b/src/Lifecycle.js
@@ -18,7 +18,7 @@ limitations under the License.
 
 import Matrix from 'matrix-js-sdk';
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import EventIndexPeg from './indexing/EventIndexPeg';
 import createMatrixClient from './utils/createMatrixClient';
 import Analytics from './Analytics';
diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 44a05c2d6e..9c939f2fd3 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -248,9 +248,4 @@ if (!global.mxMatrixClientPeg) {
     global.mxMatrixClientPeg = new _MatrixClientPeg();
 }
 
-// We export both because the syntax is slightly different with
-// our babel changes. We maintain both for backwards compatibility
-// and for babel to be happy.
-// TODO: Convert this to a single export
-export default global.mxMatrixClientPeg;
 export const MatrixClientPeg = global.mxMatrixClientPeg;
diff --git a/src/Notifier.js b/src/Notifier.js
index 73b1eae33c..0c335a8030 100644
--- a/src/Notifier.js
+++ b/src/Notifier.js
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import PlatformPeg from './PlatformPeg';
 import * as TextForEvent from './TextForEvent';
 import Analytics from './Analytics';
diff --git a/src/Presence.js b/src/Presence.js
index 8ef988f171..e3f5169c8f 100644
--- a/src/Presence.js
+++ b/src/Presence.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 import dis from "./dispatcher";
 import Timer from './utils/Timer';
 
diff --git a/src/Registration.js b/src/Registration.js
index e76e7bc5bf..ac8baa3cca 100644
--- a/src/Registration.js
+++ b/src/Registration.js
@@ -24,7 +24,7 @@ import dis from './dispatcher';
 import * as sdk from './index';
 import Modal from './Modal';
 import { _t } from './languageHandler';
-// import MatrixClientPeg from './MatrixClientPeg';
+// import {MatrixClientPeg} from './MatrixClientPeg';
 
 // Regex for what a "safe" or "Matrix-looking" localpart would be.
 // TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514
diff --git a/src/Resend.js b/src/Resend.js
index 51ec804c01..31d541630c 100644
--- a/src/Resend.js
+++ b/src/Resend.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import dis from './dispatcher';
 import { EventStatus } from 'matrix-js-sdk';
 
diff --git a/src/RoomInvite.js b/src/RoomInvite.js
index 80979da372..380bb4a7ac 100644
--- a/src/RoomInvite.js
+++ b/src/RoomInvite.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import MultiInviter from './utils/MultiInviter';
 import Modal from './Modal';
 import { getAddressType } from './UserAddress';
diff --git a/src/RoomNotifs.js b/src/RoomNotifs.js
index efc647436b..c67acaf314 100644
--- a/src/RoomNotifs.js
+++ b/src/RoomNotifs.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
 
 export const ALL_MESSAGES_LOUD = 'all_messages_loud';
diff --git a/src/Rooms.js b/src/Rooms.js
index 239e348b58..f65e0ff218 100644
--- a/src/Rooms.js
+++ b/src/Rooms.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 
 /**
  * Given a room object, return the alias we should use for it,
diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js
index c67f49ba26..99d6c533a9 100644
--- a/src/ScalarAuthClient.js
+++ b/src/ScalarAuthClient.js
@@ -18,10 +18,9 @@ limitations under the License.
 import url from 'url';
 import SettingsStore from "./settings/SettingsStore";
 import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
+import {MatrixClientPeg} from "./MatrixClientPeg";
 const request = require('browser-request');
 
-const MatrixClientPeg = require('./MatrixClientPeg');
-
 import * as Matrix from 'matrix-js-sdk';
 import SdkConfig from "./SdkConfig";
 
diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js
index c0ffc3022d..daee7e3296 100644
--- a/src/ScalarMessaging.js
+++ b/src/ScalarMessaging.js
@@ -232,7 +232,7 @@ Example:
 }
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import { MatrixEvent } from 'matrix-js-sdk';
 import dis from './dispatcher';
 import WidgetUtils from './utils/WidgetUtils';
diff --git a/src/Searching.js b/src/Searching.js
index f8976c92e4..a5d945f64b 100644
--- a/src/Searching.js
+++ b/src/Searching.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import EventIndexPeg from "./indexing/EventIndexPeg";
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 
 function serverSideSearch(term, roomId = undefined) {
     let filter;
diff --git a/src/SlashCommands.js b/src/SlashCommands.js
index b9b7866643..c855b42c29 100644
--- a/src/SlashCommands.js
+++ b/src/SlashCommands.js
@@ -18,7 +18,7 @@ limitations under the License.
 
 
 import React from 'react';
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import dis from './dispatcher';
 import * as sdk from './index';
 import {_t, _td} from './languageHandler';
diff --git a/src/Terms.js b/src/Terms.js
index f6a4850446..6ae89f9a2c 100644
--- a/src/Terms.js
+++ b/src/Terms.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import classNames from 'classnames';
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import * as sdk from './';
 import Modal from './Modal';
 
diff --git a/src/TextForEvent.js b/src/TextForEvent.js
index c3c8396e26..8a5bddf617 100644
--- a/src/TextForEvent.js
+++ b/src/TextForEvent.js
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import CallHandler from './CallHandler';
 import { _t } from './languageHandler';
 import * as Roles from './Roles';
diff --git a/src/Unread.js b/src/Unread.js
index d5c5993974..8b859a07fe 100644
--- a/src/Unread.js
+++ b/src/Unread.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-const MatrixClientPeg = require('./MatrixClientPeg');
+import {MatrixClientPeg} from "./MatrixClientPeg";
 import shouldHideEvent from './shouldHideEvent';
 const sdk = require('./index');
 
diff --git a/src/VectorConferenceHandler.js b/src/VectorConferenceHandler.js
index e0e333a371..0ade4c9daf 100644
--- a/src/VectorConferenceHandler.js
+++ b/src/VectorConferenceHandler.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import {createNewMatrixCall, Room} from "matrix-js-sdk";
 import CallHandler from './CallHandler';
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 
 // FIXME: this is Riot (Vector) specific code, but will be removed shortly when
 // we switch over to jitsi entirely for video conferencing.
diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js
index eb09685cbe..8fce6d8311 100644
--- a/src/WhoIsTyping.js
+++ b/src/WhoIsTyping.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 import { _t } from './languageHandler';
 
 module.exports = {
diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js
index 1d8e1b9cd3..d40a8ab637 100644
--- a/src/WidgetMessaging.js
+++ b/src/WidgetMessaging.js
@@ -23,7 +23,7 @@ limitations under the License.
 import FromWidgetPostMessageApi from './FromWidgetPostMessageApi';
 import ToWidgetPostMessageApi from './ToWidgetPostMessageApi';
 import Modal from "./Modal";
-import MatrixClientPeg from "./MatrixClientPeg";
+import {MatrixClientPeg} from "./MatrixClientPeg";
 import SettingsStore from "./settings/SettingsStore";
 import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog";
 import WidgetUtils from "./utils/WidgetUtils";
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index 145203136a..64c36962c4 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -18,8 +18,9 @@ const React = require("react");
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
+
 const sdk = require('../../../index');
-const MatrixClientPeg = require("../../../MatrixClientPeg");
 
 module.exports = createReactClass({
     displayName: 'EncryptedEventDialog',
diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
index 3b34c2f7a0..56d3c80549 100644
--- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
+++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
@@ -19,7 +19,7 @@ import React from 'react';
 import FileSaver from 'file-saver';
 
 import * as sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 import { scorePassword } from '../../../../utils/PasswordScorer';
 import { _t } from '../../../../languageHandler';
 
diff --git a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
index 5382aba23b..7a7d130dbe 100644
--- a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
+++ b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from "prop-types";
 import * as sdk from "../../../../index";
-import MatrixClientPeg from '../../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 import dis from "../../../../dispatcher";
 import { _t } from "../../../../languageHandler";
 import Modal from "../../../../Modal";
diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
index beb7a22157..df51650719 100644
--- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
+++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import * as sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 import { scorePassword } from '../../../../utils/PasswordScorer';
 import FileSaver from 'file-saver';
 import { _t } from '../../../../languageHandler';
diff --git a/src/autocomplete/CommunityProvider.js b/src/autocomplete/CommunityProvider.js
index dce1d279ff..e67c53b3f4 100644
--- a/src/autocomplete/CommunityProvider.js
+++ b/src/autocomplete/CommunityProvider.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import { _t } from '../languageHandler';
 import AutocompleteProvider from './AutocompleteProvider';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import QueryMatcher from './QueryMatcher';
 import {PillCompletion} from './Components';
 import * as sdk from '../index';
diff --git a/src/autocomplete/NotifProvider.js b/src/autocomplete/NotifProvider.js
index 1fb9da95c9..b433e91b05 100644
--- a/src/autocomplete/NotifProvider.js
+++ b/src/autocomplete/NotifProvider.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import AutocompleteProvider from './AutocompleteProvider';
 import { _t } from '../languageHandler';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import {PillCompletion} from './Components';
 import * as sdk from '../index';
 import type {Completion, SelectionRange} from "./Autocompleter";
diff --git a/src/autocomplete/RoomProvider.js b/src/autocomplete/RoomProvider.js
index 91b4543432..bb7f8ae0c9 100644
--- a/src/autocomplete/RoomProvider.js
+++ b/src/autocomplete/RoomProvider.js
@@ -20,7 +20,7 @@ limitations under the License.
 import React from 'react';
 import { _t } from '../languageHandler';
 import AutocompleteProvider from './AutocompleteProvider';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import QueryMatcher from './QueryMatcher';
 import {PillCompletion} from './Components';
 import {getDisplayAliasForRoom} from '../Rooms';
diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js
index 3385e13b72..59075b0752 100644
--- a/src/autocomplete/UserProvider.js
+++ b/src/autocomplete/UserProvider.js
@@ -25,7 +25,7 @@ import {PillCompletion} from './Components';
 import * as sdk from '../index';
 import QueryMatcher from './QueryMatcher';
 import _sortBy from 'lodash/sortBy';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 import type {MatrixEvent, Room, RoomMember, RoomState} from 'matrix-js-sdk';
 import {makeUserPermalink} from "../utils/permalinks/Permalinks";
diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index 8cc8a9424e..85ae414a0a 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -25,7 +25,7 @@ import { _t } from '../../languageHandler';
 import sanitizeHtml from 'sanitize-html';
 import * as sdk from '../../index';
 import dis from '../../dispatcher';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import { MatrixClient } from 'matrix-js-sdk';
 import classnames from 'classnames';
 
diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js
index ef60f71ec9..03fd2e187a 100644
--- a/src/components/structures/FilePanel.js
+++ b/src/components/structures/FilePanel.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 
 import Matrix from 'matrix-js-sdk';
 import * as sdk from '../../index';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import { _t } from '../../languageHandler';
 
 /*
diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js
index 07a9fbc521..f3e87befa3 100644
--- a/src/components/structures/GroupView.js
+++ b/src/components/structures/GroupView.js
@@ -19,7 +19,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import { getHostingLink } from '../../utils/HostingLink';
diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index 85b794f67f..2cc30a5b39 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -29,7 +29,7 @@ import { fixupColorFonts } from '../../utils/FontManager';
 import * as sdk from '../../index';
 import dis from '../../dispatcher';
 import sessionStore from '../../stores/SessionStore';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import SettingsStore from "../../settings/SettingsStore";
 import RoomListStore from "../../stores/RoomListStore";
 import { getHomePageUrl } from '../../utils/pages';
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index 1469324aaf..8dfb3dd74b 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -29,7 +29,7 @@ import 'what-input';
 
 import Analytics from "../../Analytics";
 import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
-import MatrixClientPeg from "../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 import PlatformPeg from "../../PlatformPeg";
 import SdkConfig from "../../SdkConfig";
 import * as RoomListSorter from "../../RoomListSorter";
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index 01644d8aff..54b910732a 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -24,7 +24,7 @@ import shouldHideEvent from '../../shouldHideEvent';
 import {wantsDateSeparator} from '../../DateUtils';
 import * as sdk from '../../index';
 
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import SettingsStore from '../../settings/SettingsStore';
 import {_t} from "../../languageHandler";
 
diff --git a/src/components/structures/NotificationPanel.js b/src/components/structures/NotificationPanel.js
index 470c7c8728..eb46fbe1dc 100644
--- a/src/components/structures/NotificationPanel.js
+++ b/src/components/structures/NotificationPanel.js
@@ -18,8 +18,9 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../languageHandler';
+import {MatrixClientPeg} from "../../MatrixClientPeg";
+
 const sdk = require('../../index');
-const MatrixClientPeg = require("../../MatrixClientPeg");
 
 /*
  * Component which shows the global notification list using a TimelinePanel
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index 4823b0976c..f88be944d7 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -18,9 +18,9 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
+import {ContentRepo} from "matrix-js-sdk";
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 
-const MatrixClientPeg = require('../../MatrixClientPeg');
-const ContentRepo = require("matrix-js-sdk").ContentRepo;
 const Modal = require('../../Modal');
 const sdk = require('../../index');
 const dis = require('../../dispatcher');
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index a10faa199a..487ccecd31 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
 import Matrix from 'matrix-js-sdk';
 import { _t, _td } from '../../languageHandler';
 import * as sdk from '../../index';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import Resend from '../../Resend';
 import * as cryptodevices from '../../cryptodevices';
 import dis from '../../dispatcher';
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index fbbc8b56ba..198120428b 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -32,7 +32,7 @@ import {Room} from "matrix-js-sdk";
 import { _t } from '../../languageHandler';
 import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
 
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import ContentMessages from '../../ContentMessages';
 import Modal from '../../Modal';
 import * as sdk from '../../index';
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index d8c2b96424..4763b4104b 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -29,7 +29,7 @@ const EventTimeline = Matrix.EventTimeline;
 
 const sdk = require('../../index');
 import { _t } from '../../languageHandler';
-const MatrixClientPeg = require("../../MatrixClientPeg");
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 const dis = require("../../dispatcher");
 import * as ObjectUtils from "../../ObjectUtils";
 const Modal = require("../../Modal");
diff --git a/src/components/structures/TopLeftMenuButton.js b/src/components/structures/TopLeftMenuButton.js
index 0d7af81a07..967805d099 100644
--- a/src/components/structures/TopLeftMenuButton.js
+++ b/src/components/structures/TopLeftMenuButton.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {TopLeftMenu} from '../views/context_menus/TopLeftMenu';
 import BaseAvatar from '../views/avatars/BaseAvatar';
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import * as Avatar from '../../Avatar';
 import { _t } from '../../languageHandler';
 import dis from "../../dispatcher";
diff --git a/src/components/structures/UserView.js b/src/components/structures/UserView.js
index 57235093f7..94159a1da4 100644
--- a/src/components/structures/UserView.js
+++ b/src/components/structures/UserView.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from "prop-types";
 import Matrix from "matrix-js-sdk";
-import MatrixClientPeg from "../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 import * as sdk from "../../index";
 import Modal from '../../Modal';
 import { _t } from '../../languageHandler';
diff --git a/src/components/structures/auth/PostRegistration.js b/src/components/structures/auth/PostRegistration.js
index 0395cb8d35..706ab54de4 100644
--- a/src/components/structures/auth/PostRegistration.js
+++ b/src/components/structures/auth/PostRegistration.js
@@ -18,7 +18,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import AuthPage from "../../views/auth/AuthPage";
 
diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js
index 20769be4cd..bcdb1953ba 100644
--- a/src/components/structures/auth/Registration.js
+++ b/src/components/structures/auth/Registration.js
@@ -29,7 +29,7 @@ import * as ServerType from '../../views/auth/ServerTypeSelector';
 import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
 import classNames from "classnames";
 import * as Lifecycle from '../../../Lifecycle';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import AuthPage from "../../views/auth/AuthPage";
 
 // Phases
diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js
index bdc34117d0..63f590da2e 100644
--- a/src/components/structures/auth/SoftLogout.js
+++ b/src/components/structures/auth/SoftLogout.js
@@ -21,7 +21,7 @@ import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import * as Lifecycle from '../../../Lifecycle';
 import Modal from '../../../Modal';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {sendLoginRequest} from "../../../Login";
 import url from 'url';
 import AuthPage from "../../views/auth/AuthPage";
diff --git a/src/components/views/avatars/GroupAvatar.js b/src/components/views/avatars/GroupAvatar.js
index 27122052dd..0da57bcb99 100644
--- a/src/components/views/avatars/GroupAvatar.js
+++ b/src/components/views/avatars/GroupAvatar.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 export default createReactClass({
     displayName: 'GroupAvatar',
diff --git a/src/components/views/avatars/MemberStatusMessageAvatar.js b/src/components/views/avatars/MemberStatusMessageAvatar.js
index ed73dd33b9..18af80991a 100644
--- a/src/components/views/avatars/MemberStatusMessageAvatar.js
+++ b/src/components/views/avatars/MemberStatusMessageAvatar.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {_t} from "../../../languageHandler";
 import MemberAvatar from '../avatars/MemberAvatar';
 import classNames from 'classnames';
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index d1e2ed25bb..55fe7e07b7 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -17,7 +17,7 @@ import React from "react";
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {ContentRepo} from "matrix-js-sdk";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
 import * as sdk from "../../../index";
 import * as Avatar from '../../../Avatar';
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index 876e3b10ac..3aec0e6752 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {EventStatus} from 'matrix-js-sdk';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js
index d9497d729e..fa4f4f54ba 100644
--- a/src/components/views/context_menus/RoomTileContextMenu.js
+++ b/src/components/views/context_menus/RoomTileContextMenu.js
@@ -23,7 +23,7 @@ import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 import * as sdk from '../../../index';
 import { _t, _td } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import DMRoomMap from '../../../utils/DMRoomMap';
 import * as Rooms from '../../../Rooms';
diff --git a/src/components/views/context_menus/StatusMessageContextMenu.js b/src/components/views/context_menus/StatusMessageContextMenu.js
index e9dd42f123..c7cf5607a1 100644
--- a/src/components/views/context_menus/StatusMessageContextMenu.js
+++ b/src/components/views/context_menus/StatusMessageContextMenu.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import AccessibleButton from '../elements/AccessibleButton';
 
diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js
index b9aabdc608..b75ec7ce36 100644
--- a/src/components/views/context_menus/TopLeftMenu.js
+++ b/src/components/views/context_menus/TopLeftMenu.js
@@ -23,7 +23,7 @@ import LogoutDialog from "../dialogs/LogoutDialog";
 import Modal from "../../../Modal";
 import SdkConfig from '../../../SdkConfig';
 import { getHostingLink } from '../../../utils/HostingLink';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {MenuItem} from "../../structures/ContextMenu";
 
 export class TopLeftMenu extends React.Component {
diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js
index a1cdb5d5bb..d32833b144 100644
--- a/src/components/views/dialogs/AddressPickerDialog.js
+++ b/src/components/views/dialogs/AddressPickerDialog.js
@@ -23,7 +23,7 @@ import createReactClass from 'create-react-class';
 
 import { _t, _td } from '../../../languageHandler';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import { addressTypes, getAddressType } from '../../../UserAddress.js';
 import GroupStore from '../../../stores/GroupStore';
diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js
index d83ce46360..1a4523ad80 100644
--- a/src/components/views/dialogs/BaseDialog.js
+++ b/src/components/views/dialogs/BaseDialog.js
@@ -25,7 +25,7 @@ import { MatrixClient } from 'matrix-js-sdk';
 
 import { KeyCode } from '../../../Keyboard';
 import AccessibleButton from '../elements/AccessibleButton';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from "../../../languageHandler";
 
 /**
diff --git a/src/components/views/dialogs/CreateGroupDialog.js b/src/components/views/dialogs/CreateGroupDialog.js
index b88639ba5a..d465ef26a2 100644
--- a/src/components/views/dialogs/CreateGroupDialog.js
+++ b/src/components/views/dialogs/CreateGroupDialog.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 export default createReactClass({
     displayName: 'CreateGroupDialog',
diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js
index cdc63b7f88..41b43af287 100644
--- a/src/components/views/dialogs/CreateRoomDialog.js
+++ b/src/components/views/dialogs/CreateRoomDialog.js
@@ -21,7 +21,7 @@ import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import withValidation from '../elements/Validation';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {Key} from "../../../Keyboard";
 
 export default createReactClass({
diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js
index bbf5dbe943..cd284e3be4 100644
--- a/src/components/views/dialogs/DeactivateAccountDialog.js
+++ b/src/components/views/dialogs/DeactivateAccountDialog.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 
 import * as sdk from '../../../index';
 import Analytics from '../../../Analytics';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as Lifecycle from '../../../Lifecycle';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js
index 8cf5a8536e..afb623c08b 100644
--- a/src/components/views/dialogs/DeviceVerifyDialog.js
+++ b/src/components/views/dialogs/DeviceVerifyDialog.js
@@ -19,7 +19,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js
index dfb15f0e0c..61002f27a2 100644
--- a/src/components/views/dialogs/DevtoolsDialog.js
+++ b/src/components/views/dialogs/DevtoolsDialog.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
 import SyntaxHighlight from '../elements/SyntaxHighlight';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import Field from "../elements/Field";
 
 class DevtoolsComponent extends React.Component {
diff --git a/src/components/views/dialogs/IncomingSasDialog.js b/src/components/views/dialogs/IncomingSasDialog.js
index d0a184f543..76323b55ad 100644
--- a/src/components/views/dialogs/IncomingSasDialog.js
+++ b/src/components/views/dialogs/IncomingSasDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/dialogs/LogoutDialog.js b/src/components/views/dialogs/LogoutDialog.js
index 67d6574084..64c0b77677 100644
--- a/src/components/views/dialogs/LogoutDialog.js
+++ b/src/components/views/dialogs/LogoutDialog.js
@@ -19,7 +19,7 @@ import Modal from '../../../Modal';
 import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import SettingsStore from "../../../settings/SettingsStore";
 
 export default class LogoutDialog extends React.Component {
diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.js b/src/components/views/dialogs/MessageEditHistoryDialog.js
index 24c5d3b682..2bdf2be35c 100644
--- a/src/components/views/dialogs/MessageEditHistoryDialog.js
+++ b/src/components/views/dialogs/MessageEditHistoryDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import { _t } from '../../../languageHandler';
 import * as sdk from "../../../index";
 import {wantsDateSeparator} from '../../../DateUtils';
diff --git a/src/components/views/dialogs/ReportEventDialog.js b/src/components/views/dialogs/ReportEventDialog.js
index dd5afeb477..3320477557 100644
--- a/src/components/views/dialogs/ReportEventDialog.js
+++ b/src/components/views/dialogs/ReportEventDialog.js
@@ -19,7 +19,7 @@ import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import PropTypes from "prop-types";
 import {MatrixEvent} from "matrix-js-sdk";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 /*
  * A dialog for reporting an event.
diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js
index 06a3f1301b..67b30e19c8 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.js
+++ b/src/components/views/dialogs/RoomSettingsDialog.js
@@ -25,7 +25,7 @@ import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab
 import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
 import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
 import * as sdk from "../../../index";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import dis from "../../../dispatcher";
 
 export default class RoomSettingsDialog extends React.Component {
diff --git a/src/components/views/dialogs/RoomUpgradeDialog.js b/src/components/views/dialogs/RoomUpgradeDialog.js
index d81958c5f0..dc734718d5 100644
--- a/src/components/views/dialogs/RoomUpgradeDialog.js
+++ b/src/components/views/dialogs/RoomUpgradeDialog.js
@@ -18,7 +18,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/dialogs/RoomUpgradeWarningDialog.js b/src/components/views/dialogs/RoomUpgradeWarningDialog.js
index 1ee1bec987..02534c5b35 100644
--- a/src/components/views/dialogs/RoomUpgradeWarningDialog.js
+++ b/src/components/views/dialogs/RoomUpgradeWarningDialog.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
 import * as sdk from "../../../index";
 import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Modal from "../../../Modal";
 
 export default class RoomUpgradeWarningDialog extends React.Component {
diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js
index dffb98443d..d24715cac0 100644
--- a/src/components/views/dialogs/SetMxIdDialog.js
+++ b/src/components/views/dialogs/SetMxIdDialog.js
@@ -19,7 +19,7 @@ import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import classnames from 'classnames';
 import { KeyCode } from '../../../Keyboard';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js
index 23e84bbe78..c70383061d 100644
--- a/src/components/views/dialogs/UnknownDeviceDialog.js
+++ b/src/components/views/dialogs/UnknownDeviceDialog.js
@@ -19,7 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 import { markAllDevicesKnown } from '../../../cryptodevices';
diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
index 99dd118438..e8f98edc7c 100644
--- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
+++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import * as sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 import Modal from '../../../../Modal';
 
 import { MatrixClient } from 'matrix-js-sdk';
diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
index 64bf54ce8a..c976eb81d0 100644
--- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
+++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from "prop-types";
 import * as sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 
 import { _t } from '../../../../languageHandler';
 import { Key } from "../../../../Keyboard";
diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js
index bae1ecd5c9..cb6a015d86 100644
--- a/src/components/views/directory/NetworkDropdown.js
+++ b/src/components/views/directory/NetworkDropdown.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {instanceForInstanceId} from '../../../utils/DirectoryUtils';
 
 const DEFAULT_ICON_URL = require("../../../../res/img/network-matrix.svg");
diff --git a/src/components/views/elements/AddressTile.js b/src/components/views/elements/AddressTile.js
index 5ea6ca110c..36af5059fc 100644
--- a/src/components/views/elements/AddressTile.js
+++ b/src/components/views/elements/AddressTile.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 import * as sdk from "../../../index";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import { _t } from '../../../languageHandler';
 import { UserAddressType } from '../../../UserAddress.js';
 
diff --git a/src/components/views/elements/AppPermission.js b/src/components/views/elements/AppPermission.js
index e08e008259..b96001b106 100644
--- a/src/components/views/elements/AppPermission.js
+++ b/src/components/views/elements/AppPermission.js
@@ -22,7 +22,7 @@ import url from 'url';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import WidgetUtils from "../../../utils/WidgetUtils";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 export default class AppPermission extends React.Component {
     static propTypes = {
diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js
index 05491cf4d8..4b586b1553 100644
--- a/src/components/views/elements/AppTile.js
+++ b/src/components/views/elements/AppTile.js
@@ -20,7 +20,7 @@ import url from 'url';
 import qs from 'querystring';
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import WidgetMessaging from '../../../WidgetMessaging';
 import AccessibleButton from './AccessibleButton';
 import Modal from '../../../Modal';
diff --git a/src/components/views/elements/DeviceVerifyButtons.js b/src/components/views/elements/DeviceVerifyButtons.js
index 6867406a03..a9dd919a56 100644
--- a/src/components/views/elements/DeviceVerifyButtons.js
+++ b/src/components/views/elements/DeviceVerifyButtons.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/elements/ErrorBoundary.js b/src/components/views/elements/ErrorBoundary.js
index 12708863e5..a043b350ab 100644
--- a/src/components/views/elements/ErrorBoundary.js
+++ b/src/components/views/elements/ErrorBoundary.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import PlatformPeg from '../../../PlatformPeg';
 import Modal from '../../../Modal';
 
diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js
index b2f6d0abbb..d92638e005 100644
--- a/src/components/views/elements/ImageView.js
+++ b/src/components/views/elements/ImageView.js
@@ -19,9 +19,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-
-const MatrixClientPeg = require('../../../MatrixClientPeg');
-
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {formatDate} from '../../../DateUtils';
 const filesize = require('filesize');
 const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js
index e0155d846b..df1a3196d6 100644
--- a/src/components/views/elements/PersistentApp.js
+++ b/src/components/views/elements/PersistentApp.js
@@ -20,7 +20,7 @@ import RoomViewStore from '../../../stores/RoomViewStore';
 import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
 import WidgetUtils from '../../../utils/WidgetUtils';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 module.exports = createReactClass({
     displayName: 'PersistentApp',
diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js
index b8c8f433f2..d2d7434709 100644
--- a/src/components/views/elements/Pill.js
+++ b/src/components/views/elements/Pill.js
@@ -22,7 +22,7 @@ import dis from '../../../dispatcher';
 import classNames from 'classnames';
 import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { getDisplayAliasForRoom } from '../../../Rooms';
 import FlairStore from "../../../stores/FlairStore";
 import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/Permalinks";
diff --git a/src/components/views/elements/RoomAliasField.js b/src/components/views/elements/RoomAliasField.js
index 2f3ddcb929..cacecb5005 100644
--- a/src/components/views/elements/RoomAliasField.js
+++ b/src/components/views/elements/RoomAliasField.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
 import withValidation from './Validation';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 export default class RoomAliasField extends React.PureComponent {
     static propTypes = {
diff --git a/src/components/views/emojipicker/ReactionPicker.js b/src/components/views/emojipicker/ReactionPicker.js
index c051ab40bb..96894e18d2 100644
--- a/src/components/views/emojipicker/ReactionPicker.js
+++ b/src/components/views/emojipicker/ReactionPicker.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from "prop-types";
 import EmojiPicker from "./EmojiPicker";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 class ReactionPicker extends React.Component {
     static propTypes = {
diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js
index 68020c3228..0c484435a4 100644
--- a/src/components/views/groups/GroupInviteTile.js
+++ b/src/components/views/groups/GroupInviteTile.js
@@ -24,7 +24,7 @@ import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import {_t} from '../../../languageHandler';
 import classNames from 'classnames';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
 
 // XXX this class copies a lot from RoomTile.js
diff --git a/src/components/views/messages/EditHistoryMessage.js b/src/components/views/messages/EditHistoryMessage.js
index d4fc926f03..a28f8e27d8 100644
--- a/src/components/views/messages/EditHistoryMessage.js
+++ b/src/components/views/messages/EditHistoryMessage.js
@@ -23,7 +23,7 @@ import {MatrixEvent} from 'matrix-js-sdk';
 import {pillifyLinks} from '../../../utils/pillify';
 import { _t } from '../../../languageHandler';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import Modal from '../../../Modal';
 import classNames from 'classnames';
 
diff --git a/src/components/views/messages/MAudioBody.js b/src/components/views/messages/MAudioBody.js
index e10b175bd7..a642936fec 100644
--- a/src/components/views/messages/MAudioBody.js
+++ b/src/components/views/messages/MAudioBody.js
@@ -19,7 +19,7 @@
 import React from 'react';
 import MFileBody from './MFileBody';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { decryptFile } from '../../../utils/DecryptFile';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js
index cc95bae64b..2177b110a5 100644
--- a/src/components/views/messages/MFileBody.js
+++ b/src/components/views/messages/MFileBody.js
@@ -19,7 +19,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import filesize from 'filesize';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import {decryptFile} from '../../../utils/DecryptFile';
diff --git a/src/components/views/messages/MKeyVerificationConclusion.js b/src/components/views/messages/MKeyVerificationConclusion.js
index 0bd8e2d3d8..f37f270a77 100644
--- a/src/components/views/messages/MKeyVerificationConclusion.js
+++ b/src/components/views/messages/MKeyVerificationConclusion.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import classNames from 'classnames';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import KeyVerificationStateObserver, {getNameForEventRoom, userLabelForEventRoom}
     from '../../../utils/KeyVerificationStateObserver';
diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js
index ca5b858f2f..5f0a02e6e8 100644
--- a/src/components/views/messages/MKeyVerificationRequest.js
+++ b/src/components/views/messages/MKeyVerificationRequest.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import * as sdk from '../../../index';
 import Modal from "../../../Modal";
diff --git a/src/components/views/messages/MVideoBody.js b/src/components/views/messages/MVideoBody.js
index 8366d0dd01..dfbe632e1c 100644
--- a/src/components/views/messages/MVideoBody.js
+++ b/src/components/views/messages/MVideoBody.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import MFileBody from './MFileBody';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { decryptFile } from '../../../utils/DecryptFile';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js
index e8c5563c6b..3451cdbb2d 100644
--- a/src/components/views/messages/ReactionsRow.js
+++ b/src/components/views/messages/ReactionsRow.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { isContentActionable } from '../../../utils/EventUtils';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 // The maximum number of reactions to initially show on a message.
 const MAX_ITEMS_WHEN_LIMITED = 8;
diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.js
index 22714e4fc7..a7ff7dce96 100644
--- a/src/components/views/messages/ReactionsRowButton.js
+++ b/src/components/views/messages/ReactionsRowButton.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.js b/src/components/views/messages/ReactionsRowButtonTooltip.js
index 2061a9ffc2..59e9d2ad7f 100644
--- a/src/components/views/messages/ReactionsRowButtonTooltip.js
+++ b/src/components/views/messages/ReactionsRowButtonTooltip.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import { unicodeToShortcode } from '../../../HtmlUtils';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js
index c72190ad1c..4ba7083bd2 100644
--- a/src/components/views/messages/RoomAvatarEvent.js
+++ b/src/components/views/messages/RoomAvatarEvent.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import * as sdk from '../../../index';
 import Modal from '../../../Modal';
diff --git a/src/components/views/messages/RoomCreate.js b/src/components/views/messages/RoomCreate.js
index 9bb6fcc0d8..65539da785 100644
--- a/src/components/views/messages/RoomCreate.js
+++ b/src/components/views/messages/RoomCreate.js
@@ -21,7 +21,7 @@ import createReactClass from 'create-react-class';
 import dis from '../../../dispatcher';
 import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 
 module.exports = createReactClass({
     displayName: 'RoomCreate',
diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js
index 8201cc6795..dc4accea09 100644
--- a/src/components/views/right_panel/UserInfo.js
+++ b/src/components/views/right_panel/UserInfo.js
@@ -35,7 +35,7 @@ import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
 import RoomViewStore from "../../../stores/RoomViewStore";
 import MultiInviter from "../../../utils/MultiInviter";
 import GroupStore from "../../../stores/GroupStore";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import E2EIcon from "../rooms/E2EIcon";
 import withLegacyMatrixClient from "../../../utils/withLegacyMatrixClient";
 import {useEventEmitter} from "../../../hooks/useEventEmitter";
diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js
index daf5c6edc2..2c43546c60 100644
--- a/src/components/views/room_settings/AliasSettings.js
+++ b/src/components/views/room_settings/AliasSettings.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const React = require('react');
 import PropTypes from 'prop-types';
-const MatrixClientPeg = require('../../../MatrixClientPeg');
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 const sdk = require("../../../index");
 import { _t } from '../../../languageHandler';
 import Field from "../elements/Field";
diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.js
index 76d2e5be84..56732d425d 100644
--- a/src/components/views/room_settings/RoomProfileSettings.js
+++ b/src/components/views/room_settings/RoomProfileSettings.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Field from "../elements/Field";
 import AccessibleButton from "../elements/AccessibleButton";
 import classNames from 'classnames';
diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js
index 15a2d6ac63..7e94ccad09 100644
--- a/src/components/views/room_settings/UrlPreviewSettings.js
+++ b/src/components/views/room_settings/UrlPreviewSettings.js
@@ -23,7 +23,7 @@ import * as sdk from "../../../index";
 import { _t, _td } from '../../../languageHandler';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import dis from "../../../dispatcher";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js
index 907d5bca50..d73fb633a0 100644
--- a/src/components/views/rooms/AppsDrawer.js
+++ b/src/components/views/rooms/AppsDrawer.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import AppTile from '../elements/AppTile';
 import Modal from '../../../Modal';
 import dis from '../../../dispatcher';
diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js
index 7add29af49..297e64b152 100644
--- a/src/components/views/rooms/AuxPanel.js
+++ b/src/components/views/rooms/AuxPanel.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import * as sdk from '../../../index';
 import dis from "../../../dispatcher";
 import * as ObjectUtils from '../../../ObjectUtils';
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index c3e6eb6ccb..b0a95e1188 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -33,7 +33,7 @@ import dis from '../../../dispatcher';
 import SettingsStore from "../../../settings/SettingsStore";
 import {EventStatus, MatrixClient} from 'matrix-js-sdk';
 import {formatTime} from "../../../DateUtils";
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
 import * as ObjectUtils from "../../../ObjectUtils";
 
diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js
index 2e3a3915d0..1f1792f5d0 100644
--- a/src/components/views/rooms/LinkPreviewWidget.js
+++ b/src/components/views/rooms/LinkPreviewWidget.js
@@ -19,9 +19,9 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import { linkifyElement } from '../../../HtmlUtils';
 import SettingsStore from "../../../settings/SettingsStore";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 const sdk = require('../../../index');
-const MatrixClientPeg = require('../../../MatrixClientPeg');
 const ImageUtils = require('../../../ImageUtils');
 const Modal = require('../../../Modal');
 
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index f2656dddc5..f2e85369c4 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -47,7 +47,7 @@ import MultiInviter from "../../../utils/MultiInviter";
 import SettingsStore from "../../../settings/SettingsStore";
 import E2EIcon from "./E2EIcon";
 import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {EventTimeline} from "matrix-js-sdk";
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js
index 05464b43c9..eecfd6cf96 100644
--- a/src/components/views/rooms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -24,7 +24,7 @@ import dis from '../../../dispatcher';
 import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
 import {isValid3pidInvite} from "../../../RoomInvite";
 import rate_limited_func from "../../../ratelimitedfunc";
-const MatrixClientPeg = require("../../../MatrixClientPeg");
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 const sdk = require('../../../index');
 const CallHandler = require("../../../CallHandler");
 
diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js
index ae346cbc70..8a92175f77 100644
--- a/src/components/views/rooms/MessageComposer.js
+++ b/src/components/views/rooms/MessageComposer.js
@@ -18,7 +18,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import CallHandler from '../../../CallHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import RoomViewStore from '../../../stores/RoomViewStore';
diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index c58fe677f5..5767309cc0 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -30,7 +30,7 @@ import PlainWithPillsSerializer from "../../../autocomplete/PlainWithPillsSerial
 
 import classNames from 'classnames';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import type {MatrixClient} from 'matrix-js-sdk/src/matrix';
 import {processCommandInput} from '../../../SlashCommands';
 import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
diff --git a/src/components/views/rooms/PinnedEventTile.js b/src/components/views/rooms/PinnedEventTile.js
index 1279c01049..d2715c3e63 100644
--- a/src/components/views/rooms/PinnedEventTile.js
+++ b/src/components/views/rooms/PinnedEventTile.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import dis from "../../../dispatcher";
 import AccessibleButton from "../elements/AccessibleButton";
 import MessageEvent from "../messages/MessageEvent";
diff --git a/src/components/views/rooms/PinnedEventsPanel.js b/src/components/views/rooms/PinnedEventsPanel.js
index dd2febdf39..e06e8f95a0 100644
--- a/src/components/views/rooms/PinnedEventsPanel.js
+++ b/src/components/views/rooms/PinnedEventsPanel.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import AccessibleButton from "../elements/AccessibleButton";
 import PinnedEventTile from "./PinnedEventTile";
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js
index 7611ff58ee..5a15a7518b 100644
--- a/src/components/views/rooms/RoomBreadcrumbs.js
+++ b/src/components/views/rooms/RoomBreadcrumbs.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React, {createRef} from "react";
 import dis from "../../../dispatcher";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import AccessibleButton from '../elements/AccessibleButton';
 import RoomAvatar from '../avatars/RoomAvatar';
diff --git a/src/components/views/rooms/RoomDetailRow.js b/src/components/views/rooms/RoomDetailRow.js
index b3a8b68b0d..66ec733061 100644
--- a/src/components/views/rooms/RoomDetailRow.js
+++ b/src/components/views/rooms/RoomDetailRow.js
@@ -19,7 +19,7 @@ import React, {createRef} from 'react';
 import { _t } from '../../../languageHandler';
 import { linkifyElement } from '../../../HtmlUtils';
 import { ContentRepo } from 'matrix-js-sdk';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index 9b15cffcf5..4c1452a29c 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import Modal from "../../../Modal";
 import RateLimitedFunc from '../../../ratelimitedfunc';
 
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 210c9394dc..a9b3849e79 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -23,7 +23,7 @@ import ReactDOM from "react-dom";
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-const MatrixClientPeg = require("../../../MatrixClientPeg");
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 const CallHandler = require('../../../CallHandler');
 const dis = require("../../../dispatcher");
 const sdk = require('../../../index');
diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js
index 375a4b42b1..94e7e3172b 100644
--- a/src/components/views/rooms/RoomNameEditor.js
+++ b/src/components/views/rooms/RoomNameEditor.js
@@ -17,8 +17,8 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 const sdk = require('../../../index');
-const MatrixClientPeg = require('../../../MatrixClientPeg');
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js
index 80b552ea24..04139aa93d 100644
--- a/src/components/views/rooms/RoomPreviewBar.js
+++ b/src/components/views/rooms/RoomPreviewBar.js
@@ -20,7 +20,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import classNames from 'classnames';
 import { _t } from '../../../languageHandler';
diff --git a/src/components/views/rooms/RoomRecoveryReminder.js b/src/components/views/rooms/RoomRecoveryReminder.js
index b45dd3a32c..534d198611 100644
--- a/src/components/views/rooms/RoomRecoveryReminder.js
+++ b/src/components/views/rooms/RoomRecoveryReminder.js
@@ -19,7 +19,7 @@ import PropTypes from "prop-types";
 import * as sdk from "../../../index";
 import { _t } from "../../../languageHandler";
 import Modal from "../../../Modal";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 
 export default class RoomRecoveryReminder extends React.PureComponent {
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 0b8aae9d06..10ed397727 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
 import dis from '../../../dispatcher';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import DMRoomMap from '../../../utils/DMRoomMap';
 import * as sdk from '../../../index';
 import {ContextMenu, ContextMenuButton, toRightOf} from '../../structures/ContextMenu';
diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.js b/src/components/views/rooms/RoomUpgradeWarningBar.js
index f7e167b253..dae5dbfa43 100644
--- a/src/components/views/rooms/RoomUpgradeWarningBar.js
+++ b/src/components/views/rooms/RoomUpgradeWarningBar.js
@@ -21,7 +21,7 @@ import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 
 module.exports = createReactClass({
     displayName: 'RoomUpgradeWarningBar',
diff --git a/src/components/views/rooms/SlateMessageComposer.js b/src/components/views/rooms/SlateMessageComposer.js
index 7714676565..b1f7adbe32 100644
--- a/src/components/views/rooms/SlateMessageComposer.js
+++ b/src/components/views/rooms/SlateMessageComposer.js
@@ -18,7 +18,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import { _t, _td } from '../../../languageHandler';
 import CallHandler from '../../../CallHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import RoomViewStore from '../../../stores/RoomViewStore';
diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js
index f1f1113836..67ee0d183c 100644
--- a/src/components/views/rooms/Stickerpicker.js
+++ b/src/components/views/rooms/Stickerpicker.js
@@ -16,7 +16,7 @@ limitations under the License.
 import React from 'react';
 import {_t, _td} from '../../../languageHandler';
 import AppTile from '../elements/AppTile';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import * as sdk from '../../../index';
 import dis from '../../../dispatcher';
 import AccessibleButton from '../elements/AccessibleButton';
diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.js b/src/components/views/rooms/ThirdPartyMemberInfo.js
index 991b20f583..f8d9069ca6 100644
--- a/src/components/views/rooms/ThirdPartyMemberInfo.js
+++ b/src/components/views/rooms/ThirdPartyMemberInfo.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {MatrixEvent} from "matrix-js-sdk";
 import {_t} from "../../../languageHandler";
 import dis from "../../../dispatcher";
diff --git a/src/components/views/rooms/WhoIsTypingTile.js b/src/components/views/rooms/WhoIsTypingTile.js
index 03cc899977..439ed67e40 100644
--- a/src/components/views/rooms/WhoIsTypingTile.js
+++ b/src/components/views/rooms/WhoIsTypingTile.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as WhoIsTyping from '../../../WhoIsTyping';
 import Timer from '../../../utils/Timer';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import MemberAvatar from '../avatars/MemberAvatar';
 
 module.exports = createReactClass({
diff --git a/src/components/views/settings/ChangeAvatar.js b/src/components/views/settings/ChangeAvatar.js
index 03147bc06c..7d088d9a40 100644
--- a/src/components/views/settings/ChangeAvatar.js
+++ b/src/components/views/settings/ChangeAvatar.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
diff --git a/src/components/views/settings/ChangeDisplayName.js b/src/components/views/settings/ChangeDisplayName.js
index 946fe606e5..846fac6a6c 100644
--- a/src/components/views/settings/ChangeDisplayName.js
+++ b/src/components/views/settings/ChangeDisplayName.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js
index a317c46cec..37a8b1a1dc 100644
--- a/src/components/views/settings/ChangePassword.js
+++ b/src/components/views/settings/ChangePassword.js
@@ -20,7 +20,7 @@ import Field from "../elements/Field";
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-const MatrixClientPeg = require("../../../MatrixClientPeg");
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 const Modal = require("../../../Modal");
 const sdk = require("../../../index");
 
diff --git a/src/components/views/settings/CrossSigningPanel.js b/src/components/views/settings/CrossSigningPanel.js
index 5c7f7a21fe..2b191454f6 100644
--- a/src/components/views/settings/CrossSigningPanel.js
+++ b/src/components/views/settings/CrossSigningPanel.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import * as sdk from '../../../index';
 import { accessSecretStorage } from '../../../CrossSigningManager';
diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js
index 2da0a969af..8b76b26cb9 100644
--- a/src/components/views/settings/DevicesPanel.js
+++ b/src/components/views/settings/DevicesPanel.js
@@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 
diff --git a/src/components/views/settings/DevicesPanelEntry.js b/src/components/views/settings/DevicesPanelEntry.js
index 8702f1e553..9ebce281ef 100644
--- a/src/components/views/settings/DevicesPanelEntry.js
+++ b/src/components/views/settings/DevicesPanelEntry.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {formatDate} from '../../../DateUtils';
 
 export default class DevicesPanelEntry extends React.Component {
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js
index 3eb9d5ac72..9e55ad3f06 100644
--- a/src/components/views/settings/KeyBackupPanel.js
+++ b/src/components/views/settings/KeyBackupPanel.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 import SettingsStore from '../../../../src/settings/SettingsStore';
diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js
index 15899c850c..f3448f7bb5 100644
--- a/src/components/views/settings/Notifications.js
+++ b/src/components/views/settings/Notifications.js
@@ -18,7 +18,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import SettingsStore, {SettingLevel} from '../../../settings/SettingsStore';
 import Modal from '../../../Modal';
 import {
diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js
index a878a8cc3f..7f7d2c8e8c 100644
--- a/src/components/views/settings/ProfileSettings.js
+++ b/src/components/views/settings/ProfileSettings.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React, {createRef} from 'react';
 import {_t} from "../../../languageHandler";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Field from "../elements/Field";
 import AccessibleButton from "../elements/AccessibleButton";
 import classNames from 'classnames';
diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.js
index 64a5ce751c..995959dc90 100644
--- a/src/components/views/settings/SetIdServer.js
+++ b/src/components/views/settings/SetIdServer.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
 import * as sdk from '../../../index';
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
 import dis from "../../../dispatcher";
 import { getThreepidsWithBindStatus } from '../../../boundThreepids';
diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js
index b41fe13805..5c7f9b24d3 100644
--- a/src/components/views/settings/account/EmailAddresses.js
+++ b/src/components/views/settings/account/EmailAddresses.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../languageHandler";
-import MatrixClientPeg from "../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../MatrixClientPeg";
 import Field from "../../elements/Field";
 import AccessibleButton from "../../elements/AccessibleButton";
 import * as Email from "../../../../email";
diff --git a/src/components/views/settings/account/PhoneNumbers.js b/src/components/views/settings/account/PhoneNumbers.js
index 57aa5781b1..a59fd60eca 100644
--- a/src/components/views/settings/account/PhoneNumbers.js
+++ b/src/components/views/settings/account/PhoneNumbers.js
@@ -18,7 +18,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../languageHandler";
-import MatrixClientPeg from "../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../MatrixClientPeg";
 import Field from "../../elements/Field";
 import AccessibleButton from "../../elements/AccessibleButton";
 import AddThreepid from "../../../../AddThreepid";
diff --git a/src/components/views/settings/discovery/EmailAddresses.js b/src/components/views/settings/discovery/EmailAddresses.js
index 567d2b4374..afc538bd33 100644
--- a/src/components/views/settings/discovery/EmailAddresses.js
+++ b/src/components/views/settings/discovery/EmailAddresses.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import { _t } from "../../../../languageHandler";
-import MatrixClientPeg from "../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../MatrixClientPeg";
 import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 import AddThreepid from '../../../../AddThreepid';
diff --git a/src/components/views/settings/discovery/PhoneNumbers.js b/src/components/views/settings/discovery/PhoneNumbers.js
index 84ad7d61e7..17fc99458f 100644
--- a/src/components/views/settings/discovery/PhoneNumbers.js
+++ b/src/components/views/settings/discovery/PhoneNumbers.js
@@ -19,7 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import { _t } from "../../../../languageHandler";
-import MatrixClientPeg from "../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../MatrixClientPeg";
 import * as sdk from '../../../../index';
 import Modal from '../../../../Modal';
 import AddThreepid from '../../../../AddThreepid';
diff --git a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
index 4fa3fb8649..6be868dc40 100644
--- a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Modal from "../../../../../Modal";
diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
index 4423ef9ecb..f0ebd2d7fd 100644
--- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import {MatrixClient} from "matrix-js-sdk";
diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.js b/src/components/views/settings/tabs/room/NotificationSettingsTab.js
index 448963dacf..9db27651c0 100644
--- a/src/components/views/settings/tabs/room/NotificationSettingsTab.js
+++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Notifier from "../../../../../Notifier";
 import SettingsStore from '../../../../../settings/SettingsStore';
diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
index 0c53a13e96..42947d1fb2 100644
--- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t, _td} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Modal from "../../../../../Modal";
diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
index 6dea081d96..0c66503c43 100644
--- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
 import {SettingLevel} from "../../../../../settings/SettingsStore";
diff --git a/src/components/views/settings/tabs/user/FlairUserSettingsTab.js b/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
index 0063a9a981..b5f3849729 100644
--- a/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import {_t} from "../../../../../languageHandler";
 import GroupUserSettings from "../../../groups/GroupUserSettings";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import PropTypes from "prop-types";
 import {MatrixClient} from "matrix-js-sdk";
 
diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
index d4182a51d3..908968b051 100644
--- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js
@@ -29,7 +29,7 @@ import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
 import PropTypes from "prop-types";
 import {enumerateThemes, ThemeWatcher} from "../../../../../theme";
 import PlatformPeg from "../../../../../PlatformPeg";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
 import Modal from "../../../../../Modal";
 import dis from "../../../../../dispatcher";
diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
index 875f0bfc10..0cf67a4db7 100644
--- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t, getCurrentLanguage} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import SdkConfig from "../../../../../SdkConfig";
 import createRoom from "../../../../../createRoom";
diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
index 608be0b129..575221c780 100644
--- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
@@ -20,7 +20,7 @@ import {Mjolnir} from "../../../../../mjolnir/Mjolnir";
 import {ListRule} from "../../../../../mjolnir/ListRule";
 import {BanList, RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList";
 import Modal from "../../../../../Modal";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 
 const sdk = require("../../../../..");
 
diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
index 8d0ec5bd69..e816a03e90 100644
--- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as FormattingUtils from "../../../../../utils/FormattingUtils";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Analytics from "../../../../../Analytics";
diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
index 18ea5a82be..d0119ecbbf 100644
--- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
@@ -20,9 +20,9 @@ import CallMediaHandler from "../../../../../CallMediaHandler";
 import Field from "../../../elements/Field";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import {SettingLevel} from "../../../../../settings/SettingsStore";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 const Modal = require("../../../../../Modal");
 const sdk = require("../../../../..");
-const MatrixClientPeg = require("../../../../../MatrixClientPeg");
 
 export default class VoiceUserSettingsTab extends React.Component {
     constructor() {
diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js
index abc79c38d0..f6923025d7 100644
--- a/src/components/views/toasts/VerificationRequestToast.js
+++ b/src/components/views/toasts/VerificationRequestToast.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 import Modal from "../../../Modal";
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {verificationMethods} from 'matrix-js-sdk/src/crypto';
 import KeyVerificationStateObserver, {userLabelForEventRoom} from "../../../utils/KeyVerificationStateObserver";
 import dis from "../../../dispatcher";
diff --git a/src/components/views/voip/CallView.js b/src/components/views/voip/CallView.js
index e76fbf397f..5b3b198472 100644
--- a/src/components/views/voip/CallView.js
+++ b/src/components/views/voip/CallView.js
@@ -19,7 +19,7 @@ import createReactClass from 'create-react-class';
 import dis from '../../../dispatcher';
 import CallHandler from '../../../CallHandler';
 import * as sdk from '../../../index';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/voip/IncomingCallBox.js b/src/components/views/voip/IncomingCallBox.js
index a7ad7bfdf6..4304cac912 100644
--- a/src/components/views/voip/IncomingCallBox.js
+++ b/src/components/views/voip/IncomingCallBox.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import MatrixClientPeg from '../../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import * as sdk from '../../../index';
diff --git a/src/createRoom.js b/src/createRoom.js
index e0c4922f48..ac943663ff 100644
--- a/src/createRoom.js
+++ b/src/createRoom.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from './MatrixClientPeg';
+import {MatrixClientPeg} from './MatrixClientPeg';
 import Modal from './Modal';
 import * as sdk from './index';
 import { _t } from './languageHandler';
diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js
index cf7e2d8da2..c912e31fa5 100644
--- a/src/indexing/EventIndex.js
+++ b/src/indexing/EventIndex.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import PlatformPeg from "../PlatformPeg";
-import MatrixClientPeg from "../MatrixClientPeg";
+import {MatrixClientPeg} from "../MatrixClientPeg";
 
 /*
  * Event indexing class that wraps the platform specific event indexing.
diff --git a/src/integrations/IntegrationManagers.js b/src/integrations/IntegrationManagers.js
index 8400b3dc94..b482ec73ce 100644
--- a/src/integrations/IntegrationManagers.js
+++ b/src/integrations/IntegrationManagers.js
@@ -20,7 +20,7 @@ import Modal from '../Modal';
 import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
 import type {MatrixClient, MatrixEvent, Room} from "matrix-js-sdk";
 import WidgetUtils from "../utils/WidgetUtils";
-import MatrixClientPeg from "../MatrixClientPeg";
+import {MatrixClientPeg} from "../MatrixClientPeg";
 import {AutoDiscovery} from "matrix-js-sdk";
 import SettingsStore from "../settings/SettingsStore";
 
diff --git a/src/mjolnir/BanList.js b/src/mjolnir/BanList.js
index 60a924a52b..21cd5d4cf7 100644
--- a/src/mjolnir/BanList.js
+++ b/src/mjolnir/BanList.js
@@ -17,7 +17,7 @@ limitations under the License.
 // Inspiration largely taken from Mjolnir itself
 
 import {ListRule, RECOMMENDATION_BAN, recommendationToStable} from "./ListRule";
-import MatrixClientPeg from "../MatrixClientPeg";
+import {MatrixClientPeg} from "../MatrixClientPeg";
 
 export const RULE_USER = "m.room.rule.user";
 export const RULE_ROOM = "m.room.rule.room";
diff --git a/src/mjolnir/Mjolnir.js b/src/mjolnir/Mjolnir.js
index 7539dfafb0..4970d8e8af 100644
--- a/src/mjolnir/Mjolnir.js
+++ b/src/mjolnir/Mjolnir.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from "../MatrixClientPeg";
+import {MatrixClientPeg} from "../MatrixClientPeg";
 import {ALL_RULE_TYPES, BanList} from "./BanList";
 import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
 import {_t} from "../languageHandler";
diff --git a/src/rageshake/submit-rageshake.js b/src/rageshake/submit-rageshake.js
index 457958eb82..019da10d52 100644
--- a/src/rageshake/submit-rageshake.js
+++ b/src/rageshake/submit-rageshake.js
@@ -18,7 +18,7 @@ limitations under the License.
 
 import pako from 'pako';
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import PlatformPeg from '../PlatformPeg';
 import { _t } from '../languageHandler';
 
diff --git a/src/settings/controllers/NotificationControllers.js b/src/settings/controllers/NotificationControllers.js
index 37d318eb1d..ada4155206 100644
--- a/src/settings/controllers/NotificationControllers.js
+++ b/src/settings/controllers/NotificationControllers.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import SettingController from "./SettingController";
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 
 // XXX: This feels wrong.
 import {PushProcessor} from "matrix-js-sdk/src/pushprocessor";
diff --git a/src/settings/handlers/AccountSettingsHandler.js b/src/settings/handlers/AccountSettingsHandler.js
index 7b05ad0c1b..fea2e92c62 100644
--- a/src/settings/handlers/AccountSettingsHandler.js
+++ b/src/settings/handlers/AccountSettingsHandler.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
 import {SettingLevel} from "../SettingsStore";
 
diff --git a/src/settings/handlers/DeviceSettingsHandler.js b/src/settings/handlers/DeviceSettingsHandler.js
index ed61e9f3be..44f89b9086 100644
--- a/src/settings/handlers/DeviceSettingsHandler.js
+++ b/src/settings/handlers/DeviceSettingsHandler.js
@@ -17,7 +17,7 @@ limitations under the License.
 */
 
 import SettingsHandler from "./SettingsHandler";
-import MatrixClientPeg from "../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 import {SettingLevel} from "../SettingsStore";
 
 /**
diff --git a/src/settings/handlers/RoomAccountSettingsHandler.js b/src/settings/handlers/RoomAccountSettingsHandler.js
index 0206711db2..1e9d3f7bed 100644
--- a/src/settings/handlers/RoomAccountSettingsHandler.js
+++ b/src/settings/handlers/RoomAccountSettingsHandler.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
 import {SettingLevel} from "../SettingsStore";
 
diff --git a/src/settings/handlers/RoomSettingsHandler.js b/src/settings/handlers/RoomSettingsHandler.js
index 79626e2186..6407818450 100644
--- a/src/settings/handlers/RoomSettingsHandler.js
+++ b/src/settings/handlers/RoomSettingsHandler.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../../MatrixClientPeg';
+import {MatrixClientPeg} from '../../MatrixClientPeg';
 import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
 import {SettingLevel} from "../SettingsStore";
 
diff --git a/src/stores/ActiveWidgetStore.js b/src/stores/ActiveWidgetStore.js
index 82a7f7932c..60ea3f9106 100644
--- a/src/stores/ActiveWidgetStore.js
+++ b/src/stores/ActiveWidgetStore.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import EventEmitter from 'events';
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 /**
  * Stores information about the widgets active in the app right now:
diff --git a/src/stores/GroupStore.js b/src/stores/GroupStore.js
index 637e87b728..f691a33e6f 100644
--- a/src/stores/GroupStore.js
+++ b/src/stores/GroupStore.js
@@ -17,7 +17,7 @@ limitations under the License.
 import EventEmitter from 'events';
 import { groupMemberFromApiObject, groupRoomFromApiObject } from '../groups';
 import FlairStore from './FlairStore';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 function parseMembersResponse(response) {
     return response.chunk.map((apiMember) => groupMemberFromApiObject(apiMember));
diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js
index 8b25eba356..a96174234a 100644
--- a/src/stores/RoomViewStore.js
+++ b/src/stores/RoomViewStore.js
@@ -16,7 +16,7 @@ limitations under the License.
 */
 import dis from '../dispatcher';
 import {Store} from 'flux/utils';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import * as sdk from '../index';
 import Modal from '../Modal';
 import { _t } from '../languageHandler';
diff --git a/src/stores/TagOrderStore.js b/src/stores/TagOrderStore.js
index 48a8817270..3ca9e39560 100644
--- a/src/stores/TagOrderStore.js
+++ b/src/stores/TagOrderStore.js
@@ -18,7 +18,7 @@ import dis from '../dispatcher';
 import GroupStore from './GroupStore';
 import Analytics from '../Analytics';
 import * as RoomNotifs from "../RoomNotifs";
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 const INITIAL_STATE = {
     orderedTags: null,
diff --git a/src/stores/TypingStore.js b/src/stores/TypingStore.js
index 71ae4f55a3..e86d698eac 100644
--- a/src/stores/TypingStore.js
+++ b/src/stores/TypingStore.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from "../MatrixClientPeg";
+import {MatrixClientPeg} from "../MatrixClientPeg";
 import SettingsStore from "../settings/SettingsStore";
 import Timer from "../utils/Timer";
 
diff --git a/src/utils/DMRoomMap.js b/src/utils/DMRoomMap.js
index af65b6f001..de6d42e4a2 100644
--- a/src/utils/DMRoomMap.js
+++ b/src/utils/DMRoomMap.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import _uniq from 'lodash/uniq';
 
 /**
diff --git a/src/utils/DecryptFile.js b/src/utils/DecryptFile.js
index f193bd7709..b87b723ed7 100644
--- a/src/utils/DecryptFile.js
+++ b/src/utils/DecryptFile.js
@@ -20,7 +20,7 @@ import encrypt from 'browser-encrypt-attachment';
 // Pull in a fetch polyfill so we can download encrypted attachments.
 import 'isomorphic-fetch';
 // Grab the client so that we can turn mxc:// URLs into https:// URLS.
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 // WARNING: We have to be very careful about what mime-types we allow into blobs,
 // as for performance reasons these are now rendered via URL.createObjectURL()
diff --git a/src/utils/EventUtils.js b/src/utils/EventUtils.js
index 29af5ca9b5..8acf5ae396 100644
--- a/src/utils/EventUtils.js
+++ b/src/utils/EventUtils.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import { EventStatus } from 'matrix-js-sdk';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import shouldHideEvent from "../shouldHideEvent";
 /**
  * Returns whether an event should allow actions like reply, reactions, edit, etc.
diff --git a/src/utils/HostingLink.js b/src/utils/HostingLink.js
index ff1ac3d063..580ed00de5 100644
--- a/src/utils/HostingLink.js
+++ b/src/utils/HostingLink.js
@@ -18,7 +18,7 @@ import url from 'url';
 import qs from 'qs';
 
 import SdkConfig from '../SdkConfig';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 export function getHostingLink(campaign) {
     const hostingLink = SdkConfig.get().hosting_signup_link;
diff --git a/src/utils/IdentityServerUtils.js b/src/utils/IdentityServerUtils.js
index cf180e3026..093d4eeabf 100644
--- a/src/utils/IdentityServerUtils.js
+++ b/src/utils/IdentityServerUtils.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import { SERVICE_TYPES } from 'matrix-js-sdk';
 import SdkConfig from '../SdkConfig';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 
 export function getDefaultIdentityServerUrl() {
     return SdkConfig.get()['validated_server_config']['isUrl'];
diff --git a/src/utils/KeyVerificationStateObserver.js b/src/utils/KeyVerificationStateObserver.js
index 2f7c0367ad..d84a5f584e 100644
--- a/src/utils/KeyVerificationStateObserver.js
+++ b/src/utils/KeyVerificationStateObserver.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import { _t } from '../languageHandler';
 
 const SUB_EVENT_TYPES_OF_INTEREST = ["start", "cancel", "done"];
diff --git a/src/utils/MultiInviter.js b/src/utils/MultiInviter.js
index 2ea1da5bcc..7d1c900360 100644
--- a/src/utils/MultiInviter.js
+++ b/src/utils/MultiInviter.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import {getAddressType} from '../UserAddress';
 import GroupStore from '../stores/GroupStore';
 import {_t} from "../languageHandler";
diff --git a/src/utils/PasswordScorer.js b/src/utils/PasswordScorer.js
index 3c366a73f8..9d89942bf5 100644
--- a/src/utils/PasswordScorer.js
+++ b/src/utils/PasswordScorer.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import zxcvbn from 'zxcvbn';
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import { _t, _td } from '../languageHandler';
 
 const ZXCVBN_USER_INPUTS = [
diff --git a/src/utils/WidgetUtils.js b/src/utils/WidgetUtils.js
index 9bab78dee4..c09cd8a858 100644
--- a/src/utils/WidgetUtils.js
+++ b/src/utils/WidgetUtils.js
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import SdkConfig from "../SdkConfig";
 import dis from '../dispatcher';
 import * as url from "url";
diff --git a/src/utils/permalinks/Permalinks.js b/src/utils/permalinks/Permalinks.js
index 4b97d1664f..591cdbb576 100644
--- a/src/utils/permalinks/Permalinks.js
+++ b/src/utils/permalinks/Permalinks.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import MatrixClientPeg from "../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../MatrixClientPeg";
 import isIp from "is-ip";
 import * as utils from 'matrix-js-sdk/src/utils';
 import SpecPermalinkConstructor, {baseUrl as matrixtoBaseUrl} from "./SpecPermalinkConstructor";
diff --git a/src/utils/pillify.js b/src/utils/pillify.js
index 044b04181e..8c2eda5f71 100644
--- a/src/utils/pillify.js
+++ b/src/utils/pillify.js
@@ -15,7 +15,7 @@ limitations under the License.
 */
 
 import ReactDOM from 'react-dom';
-import MatrixClientPeg from '../MatrixClientPeg';
+import {MatrixClientPeg} from '../MatrixClientPeg';
 import SettingsStore from "../settings/SettingsStore";
 import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
 import * as sdk from '../index';
diff --git a/test/ScalarAuthClient-test.js b/test/ScalarAuthClient-test.js
index 7e944189a6..a3a95c7053 100644
--- a/test/ScalarAuthClient-test.js
+++ b/test/ScalarAuthClient-test.js
@@ -19,7 +19,7 @@ import expect from 'expect';
 import sinon from 'sinon';
 
 import ScalarAuthClient from '../src/ScalarAuthClient';
-import MatrixClientPeg from '../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../src/MatrixClientPeg';
 import { stubClient } from './test-utils';
 
 describe('ScalarAuthClient', function() {
diff --git a/test/Terms-test.js b/test/Terms-test.js
index 3fc7b56e42..6b102a5eda 100644
--- a/test/Terms-test.js
+++ b/test/Terms-test.js
@@ -22,7 +22,7 @@ import * as Matrix from 'matrix-js-sdk';
 
 import { startTermsFlow, Service } from '../src/Terms';
 import { stubClient } from './test-utils';
-import MatrixClientPeg from '../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../src/MatrixClientPeg';
 
 const POLICY_ONE = {
     version: "six",
diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index b0768d3911..45b524c4ed 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -20,7 +20,7 @@ import ReactTestUtils from 'react-dom/test-utils';
 import expect from 'expect';
 
 import MockHttpBackend from 'matrix-mock-request';
-import MatrixClientPeg from '../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../src/MatrixClientPeg';
 import sdk from 'matrix-react-sdk';
 import Matrix from 'matrix-js-sdk';
 
diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js
index 7c52512bc2..60a392047b 100644
--- a/test/components/structures/MessagePanel-test.js
+++ b/test/components/structures/MessagePanel-test.js
@@ -29,7 +29,7 @@ import { EventEmitter } from "events";
 const sdk = require('matrix-react-sdk');
 
 const MessagePanel = sdk.getComponent('structures.MessagePanel');
-import MatrixClientPeg from '../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../src/MatrixClientPeg';
 import Matrix from 'matrix-js-sdk';
 
 const test_utils = require('test-utils');
diff --git a/test/components/views/dialogs/InteractiveAuthDialog-test.js b/test/components/views/dialogs/InteractiveAuthDialog-test.js
index 5f90e0f21c..850e4e94d5 100644
--- a/test/components/views/dialogs/InteractiveAuthDialog-test.js
+++ b/test/components/views/dialogs/InteractiveAuthDialog-test.js
@@ -22,7 +22,7 @@ import sinon from 'sinon';
 import MatrixReactTestUtils from 'matrix-react-test-utils';
 
 import sdk from 'matrix-react-sdk';
-import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 
 import * as test_utils from '../../../test-utils';
 import {sleep} from "../../../../src/utils/promise";
diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js
index 3922610644..32bf25f570 100644
--- a/test/components/views/groups/GroupMemberList-test.js
+++ b/test/components/views/groups/GroupMemberList-test.js
@@ -20,7 +20,7 @@ import ReactTestUtils from "react-dom/test-utils";
 import expect from "expect";
 
 import MockHttpBackend from "matrix-mock-request";
-import MatrixClientPeg from "../../../../src/MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
 import sdk from "matrix-react-sdk";
 import Matrix from "matrix-js-sdk";
 
diff --git a/test/components/views/rooms/MemberList-test.js b/test/components/views/rooms/MemberList-test.js
index 9a1439c2f7..635d0753fd 100644
--- a/test/components/views/rooms/MemberList-test.js
+++ b/test/components/views/rooms/MemberList-test.js
@@ -7,7 +7,7 @@ import lolex from 'lolex';
 import * as TestUtils from 'test-utils';
 
 import sdk from '../../../../src/index';
-import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 
 import {Room, RoomMember, User} from 'matrix-js-sdk';
 
diff --git a/test/components/views/rooms/MessageComposerInput-test.js b/test/components/views/rooms/MessageComposerInput-test.js
index 60380eecd2..6adae13181 100644
--- a/test/components/views/rooms/MessageComposerInput-test.js
+++ b/test/components/views/rooms/MessageComposerInput-test.js
@@ -6,7 +6,7 @@ import sinon from 'sinon';
 import * as testUtils from '../../../test-utils';
 import sdk from 'matrix-react-sdk';
 const MessageComposerInput = sdk.getComponent('views.rooms.MessageComposerInput');
-import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 import {sleep} from "../../../../src/utils/promise";
 
 function addTextToDraft(text) {
diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js
index 68168fcf29..0df968824d 100644
--- a/test/components/views/rooms/RoomList-test.js
+++ b/test/components/views/rooms/RoomList-test.js
@@ -7,7 +7,7 @@ import lolex from 'lolex';
 import * as TestUtils from 'test-utils';
 
 import sdk from '../../../../src/index';
-import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 import { DragDropContext } from 'react-beautiful-dnd';
 
 import dis from '../../../../src/dispatcher';
diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js
index 1c0bfd95dc..b0ed832c6d 100644
--- a/test/components/views/rooms/RoomSettings-test.js
+++ b/test/components/views/rooms/RoomSettings-test.js
@@ -6,7 +6,7 @@
 // import * as testUtils from '../../../test-utils';
 // import sdk from 'matrix-react-sdk';
 // const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
-// import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+// import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 // import SettingsStore from '../../../../src/settings/SettingsStore';
 //
 //

From f1ac3d2f646007946d5a8ce440ec630833c6a5f6 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 14:41:07 -0700
Subject: [PATCH 37/86] Convert imports to ES6 from CommonJS

This is needed because `require()` means something different in webpack - it ends up importing the module as something we didn't expect (and is occasionally async)
---
 src/ScalarAuthClient.js                           |  2 +-
 src/Unread.js                                     |  2 +-
 src/Velociraptor.js                               |  6 +++---
 src/VelocityBounce.js                             |  2 +-
 src/actions/RoomListActions.js                    |  1 -
 .../views/dialogs/EncryptedEventDialog.js         |  2 +-
 .../dialogs/keybackup/CreateKeyBackupDialog.js    |  1 -
 src/autocomplete/CommunityProvider.js             |  2 +-
 src/autocomplete/DuckDuckGoProvider.js            |  2 +-
 src/autocomplete/NotifProvider.js                 |  2 +-
 src/autocomplete/RoomProvider.js                  |  2 +-
 src/autocomplete/UserProvider.js                  |  2 +-
 src/components/structures/InteractiveAuth.js      |  4 +---
 src/components/structures/MatrixChat.js           |  2 +-
 src/components/structures/NotificationPanel.js    |  3 +--
 src/components/structures/RoomDirectory.js        |  8 +++-----
 src/components/structures/TimelinePanel.js        | 15 ++++++---------
 src/components/structures/UploadBar.js            |  4 ++--
 src/components/views/avatars/MemberAvatar.js      |  4 ++--
 src/components/views/elements/ImageView.js        |  8 ++++----
 .../views/room_settings/AliasSettings.js          |  6 +++---
 src/components/views/rooms/EventTile.js           |  9 +++------
 src/components/views/rooms/LinkPreviewWidget.js   |  7 +++----
 src/components/views/rooms/MemberList.js          |  4 ++--
 src/components/views/rooms/MemberTile.js          |  6 ++----
 src/components/views/rooms/ReadReceiptMarker.js   |  9 +++------
 src/components/views/rooms/RoomList.js            | 11 +++++------
 src/components/views/rooms/RoomNameEditor.js      |  2 +-
 src/components/views/rooms/SearchBar.js           |  4 ++--
 src/components/views/rooms/UserTile.js            |  3 +--
 src/components/views/settings/ChangePassword.js   |  6 ++----
 .../settings/tabs/user/LabsUserSettingsTab.js     |  2 +-
 .../settings/tabs/user/MjolnirUserSettingsTab.js  |  3 +--
 .../tabs/user/NotificationUserSettingsTab.js      |  2 +-
 .../settings/tabs/user/VoiceUserSettingsTab.js    |  4 ++--
 src/dispatcher.js                                 |  2 +-
 src/utils/createMatrixClient.js                   |  2 +-
 src/utils/permalinks/Permalinks.js                |  3 +--
 38 files changed, 67 insertions(+), 92 deletions(-)

diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js
index 99d6c533a9..819fe3c998 100644
--- a/src/ScalarAuthClient.js
+++ b/src/ScalarAuthClient.js
@@ -19,7 +19,7 @@ import url from 'url';
 import SettingsStore from "./settings/SettingsStore";
 import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
 import {MatrixClientPeg} from "./MatrixClientPeg";
-const request = require('browser-request');
+import request from "browser-request";
 
 import * as Matrix from 'matrix-js-sdk';
 import SdkConfig from "./SdkConfig";
diff --git a/src/Unread.js b/src/Unread.js
index 8b859a07fe..6aaa733f20 100644
--- a/src/Unread.js
+++ b/src/Unread.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import {MatrixClientPeg} from "./MatrixClientPeg";
 import shouldHideEvent from './shouldHideEvent';
-const sdk = require('./index');
+import * as sdk from "./index";
 
 module.exports = {
     /**
diff --git a/src/Velociraptor.js b/src/Velociraptor.js
index 245ca6648b..ce52f60dbd 100644
--- a/src/Velociraptor.js
+++ b/src/Velociraptor.js
@@ -1,7 +1,7 @@
-const React = require('react');
-const ReactDom = require('react-dom');
+import React from "react";
+import ReactDom from "react-dom";
+import Velocity from "velocity-animate";
 import PropTypes from 'prop-types';
-const Velocity = require('velocity-animate');
 
 /**
  * The Velociraptor contains components and animates transitions with velocity.
diff --git a/src/VelocityBounce.js b/src/VelocityBounce.js
index db216f81fb..ffbf7de829 100644
--- a/src/VelocityBounce.js
+++ b/src/VelocityBounce.js
@@ -1,4 +1,4 @@
-const Velocity = require('velocity-animate');
+import Velocity from "velocity-animate";
 
 // courtesy of https://github.com/julianshapiro/velocity/issues/283
 // We only use easeOutBounce (easeInBounce is just sort of nonsensical)
diff --git a/src/actions/RoomListActions.js b/src/actions/RoomListActions.js
index 854fa1b367..d534fe5d1d 100644
--- a/src/actions/RoomListActions.js
+++ b/src/actions/RoomListActions.js
@@ -16,7 +16,6 @@ limitations under the License.
 
 import { asyncAction } from './actionCreators';
 import RoomListStore from '../stores/RoomListStore';
-
 import Modal from '../Modal';
 import * as Rooms from '../Rooms';
 import { _t } from '../languageHandler';
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index 64c36962c4..45cc154906 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-const React = require("react");
+import React from "react";
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
index 56d3c80549..aec9162c97 100644
--- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
+++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
@@ -17,7 +17,6 @@ limitations under the License.
 
 import React from 'react';
 import FileSaver from 'file-saver';
-
 import * as sdk from '../../../../index';
 import {MatrixClientPeg} from '../../../../MatrixClientPeg';
 import { scorePassword } from '../../../../utils/PasswordScorer';
diff --git a/src/autocomplete/CommunityProvider.js b/src/autocomplete/CommunityProvider.js
index e67c53b3f4..b863603aae 100644
--- a/src/autocomplete/CommunityProvider.js
+++ b/src/autocomplete/CommunityProvider.js
@@ -46,7 +46,7 @@ export default class CommunityProvider extends AutocompleteProvider {
         });
     }
 
-    async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
+    async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
         const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
 
         // Disable autocompletions when composing commands because of various issues
diff --git a/src/autocomplete/DuckDuckGoProvider.js b/src/autocomplete/DuckDuckGoProvider.js
index 49ef7dfb43..ca1b1478cc 100644
--- a/src/autocomplete/DuckDuckGoProvider.js
+++ b/src/autocomplete/DuckDuckGoProvider.js
@@ -37,7 +37,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider {
          + `&format=json&no_redirect=1&no_html=1&t=${encodeURIComponent(REFERRER)}`;
     }
 
-    async getCompletions(query: string, selection: SelectionRange, force?: boolean = false) {
+    async getCompletions(query: string, selection: SelectionRange, force: boolean = false) {
         const {command, range} = this.getCurrentCommand(query, selection);
         if (!query || !command) {
             return [];
diff --git a/src/autocomplete/NotifProvider.js b/src/autocomplete/NotifProvider.js
index b433e91b05..e7c8f6f70d 100644
--- a/src/autocomplete/NotifProvider.js
+++ b/src/autocomplete/NotifProvider.js
@@ -30,7 +30,7 @@ export default class NotifProvider extends AutocompleteProvider {
         this.room = room;
     }
 
-    async getCompletions(query: string, selection: SelectionRange, force?:boolean = false): Array<Completion> {
+    async getCompletions(query: string, selection: SelectionRange, force:boolean = false): Array<Completion> {
         const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
 
         const client = MatrixClientPeg.get();
diff --git a/src/autocomplete/RoomProvider.js b/src/autocomplete/RoomProvider.js
index bb7f8ae0c9..b28c79ac54 100644
--- a/src/autocomplete/RoomProvider.js
+++ b/src/autocomplete/RoomProvider.js
@@ -48,7 +48,7 @@ export default class RoomProvider extends AutocompleteProvider {
         });
     }
 
-    async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
+    async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
         const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
 
         const client = MatrixClientPeg.get();
diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js
index 59075b0752..7fd600b136 100644
--- a/src/autocomplete/UserProvider.js
+++ b/src/autocomplete/UserProvider.js
@@ -91,7 +91,7 @@ export default class UserProvider extends AutocompleteProvider {
         this.users = null;
     }
 
-    async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
+    async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
         const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
 
         // lazy-load user list into matcher
diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js
index e7194e9fa4..53bb990e26 100644
--- a/src/components/structures/InteractiveAuth.js
+++ b/src/components/structures/InteractiveAuth.js
@@ -15,9 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import Matrix from 'matrix-js-sdk';
-const InteractiveAuth = Matrix.InteractiveAuth;
-
+import {InteractiveAuth} from "matrix-js-sdk";
 import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index 8dfb3dd74b..0713290a26 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -20,7 +20,7 @@ limitations under the License.
 import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import Matrix from "matrix-js-sdk";
+import * as Matrix from "matrix-js-sdk";
 
 // focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
 import 'focus-visible';
diff --git a/src/components/structures/NotificationPanel.js b/src/components/structures/NotificationPanel.js
index eb46fbe1dc..70ea24ad17 100644
--- a/src/components/structures/NotificationPanel.js
+++ b/src/components/structures/NotificationPanel.js
@@ -19,8 +19,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import { _t } from '../../languageHandler';
 import {MatrixClientPeg} from "../../MatrixClientPeg";
-
-const sdk = require('../../index');
+import * as sdk from "../../index";
 
 /*
  * Component which shows the global notification list using a TimelinePanel
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index f88be944d7..94a6d04b55 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -20,11 +20,9 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import {ContentRepo} from "matrix-js-sdk";
 import {MatrixClientPeg} from "../../MatrixClientPeg";
-
-const Modal = require('../../Modal');
-const sdk = require('../../index');
-const dis = require('../../dispatcher');
-
+import * as sdk from "../../index";
+import dis from "../../dispatcher";
+import Modal from "../../Modal";
 import { linkifyAndSanitizeHtml } from '../../HtmlUtils';
 import PropTypes from 'prop-types';
 import { _t } from '../../languageHandler';
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 4763b4104b..3996b74922 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -18,22 +18,19 @@ limitations under the License.
 */
 
 import SettingsStore from "../../settings/SettingsStore";
-
 import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
 import ReactDOM from "react-dom";
 import PropTypes from 'prop-types';
-
-const Matrix = require("matrix-js-sdk");
-const EventTimeline = Matrix.EventTimeline;
-
-const sdk = require('../../index');
+import {EventTimeline} from "matrix-js-sdk";
+import * as Matrix from "matrix-js-sdk";
 import { _t } from '../../languageHandler';
 import {MatrixClientPeg} from "../../MatrixClientPeg";
-const dis = require("../../dispatcher");
 import * as ObjectUtils from "../../ObjectUtils";
-const Modal = require("../../Modal");
-const UserActivity = require("../../UserActivity");
+import UserActivity from "../../UserActivity";
+import Modal from "../../Modal";
+import dis from "../../dispatcher";
+import * as sdk from "../../index";
 import { KeyCode } from '../../Keyboard';
 import Timer from '../../utils/Timer';
 import shouldHideEvent from '../../shouldHideEvent';
diff --git a/src/components/structures/UploadBar.js b/src/components/structures/UploadBar.js
index da0ca7fe99..adaf8824fc 100644
--- a/src/components/structures/UploadBar.js
+++ b/src/components/structures/UploadBar.js
@@ -18,8 +18,8 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import ContentMessages from '../../ContentMessages';
-const dis = require('../../dispatcher');
-const filesize = require('filesize');
+import dis from "../../dispatcher";
+import filesize from "filesize";
 import { _t } from '../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js
index cb9ef70168..6961a00d6d 100644
--- a/src/components/views/avatars/MemberAvatar.js
+++ b/src/components/views/avatars/MemberAvatar.js
@@ -18,8 +18,8 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as Avatar from '../../../Avatar';
-const sdk = require("../../../index");
-const dispatcher = require("../../../dispatcher");
+import * as sdk from "../../../index";
+import dis from "../../../dispatcher";
 
 module.exports = createReactClass({
     displayName: 'MemberAvatar',
diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js
index d92638e005..e12a15766e 100644
--- a/src/components/views/elements/ImageView.js
+++ b/src/components/views/elements/ImageView.js
@@ -21,11 +21,11 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {formatDate} from '../../../DateUtils';
-const filesize = require('filesize');
-const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
-const Modal = require('../../../Modal');
-const sdk = require('../../../index');
 import { _t } from '../../../languageHandler';
+import filesize from "filesize";
+import AccessibleButton from "./AccessibleButton";
+import Modal from "../../../Modal";
+import * as sdk from "../../../index";
 
 export default class ImageView extends React.Component {
     static propTypes = {
diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js
index 2c43546c60..b0d291ac10 100644
--- a/src/components/views/room_settings/AliasSettings.js
+++ b/src/components/views/room_settings/AliasSettings.js
@@ -15,14 +15,14 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-const React = require('react');
+import React from "react";
 import PropTypes from 'prop-types';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-const sdk = require("../../../index");
+import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 import Field from "../elements/Field";
 import ErrorDialog from "../dialogs/ErrorDialog";
-const Modal = require("../../../Modal");
+import Modal from "../../../Modal";
 
 export default class AliasSettings extends React.Component {
     static propTypes = {
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index b0a95e1188..de3af77946 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -18,17 +18,14 @@ limitations under the License.
 */
 
 import ReplyThread from "../elements/ReplyThread";
-
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-const classNames = require("classnames");
+import classNames from "classnames";
 import { _t, _td } from '../../../languageHandler';
 import * as TextForEvent from "../../../TextForEvent";
-const Modal = require('../../../Modal');
-
-const sdk = require('../../../index');
-
+import Modal from "../../../Modal";
+import * as sdk from "../../../index";
 import dis from '../../../dispatcher';
 import SettingsStore from "../../../settings/SettingsStore";
 import {EventStatus, MatrixClient} from 'matrix-js-sdk';
diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js
index 1f1792f5d0..f0b51ff299 100644
--- a/src/components/views/rooms/LinkPreviewWidget.js
+++ b/src/components/views/rooms/LinkPreviewWidget.js
@@ -20,10 +20,9 @@ import createReactClass from 'create-react-class';
 import { linkifyElement } from '../../../HtmlUtils';
 import SettingsStore from "../../../settings/SettingsStore";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-
-const sdk = require('../../../index');
-const ImageUtils = require('../../../ImageUtils');
-const Modal = require('../../../Modal');
+import * as sdk from "../../../index";
+import Modal from "../../../Modal";
+import * as ImageUtils from "../../../ImageUtils";
 
 module.exports = createReactClass({
     displayName: 'LinkPreviewWidget',
diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js
index eecfd6cf96..7d47bdb4b8 100644
--- a/src/components/views/rooms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -25,8 +25,8 @@ import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
 import {isValid3pidInvite} from "../../../RoomInvite";
 import rate_limited_func from "../../../ratelimitedfunc";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-const sdk = require('../../../index');
-const CallHandler = require("../../../CallHandler");
+import * as sdk from "../../../index";
+import CallHandler from "../../../CallHandler";
 
 const INITIAL_LOAD_NUM_MEMBERS = 30;
 const INITIAL_LOAD_NUM_INVITED = 5;
diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js
index c002849450..c992b9d4f3 100644
--- a/src/components/views/rooms/MemberTile.js
+++ b/src/components/views/rooms/MemberTile.js
@@ -15,13 +15,11 @@ limitations under the License.
 */
 
 import SettingsStore from "../../../settings/SettingsStore";
-
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-
-const sdk = require('../../../index');
-const dis = require('../../../dispatcher');
+import * as sdk from "../../../index";
+import dis from "../../../dispatcher";
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js
index 27c5e8c20e..d8ce58342a 100644
--- a/src/components/views/rooms/ReadReceiptMarker.js
+++ b/src/components/views/rooms/ReadReceiptMarker.js
@@ -18,14 +18,11 @@ import React from 'react';
 import ReactDOM from 'react-dom';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-
-const sdk = require('../../../index');
-
-const Velociraptor = require('../../../Velociraptor');
-require('../../../VelocityBounce');
+import('../../../VelocityBounce');
 import { _t } from '../../../languageHandler';
-
 import {formatDate} from '../../../DateUtils';
+import Velociraptor from "../../../Velociraptor";
+import * as sdk from "../../../index";
 
 let bounce = false;
 try {
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index a9b3849e79..ab15ab5a83 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -17,29 +17,28 @@ limitations under the License.
 
 import SettingsStore from "../../../settings/SettingsStore";
 import Timer from "../../../utils/Timer";
-
 import React from "react";
 import ReactDOM from "react-dom";
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-const CallHandler = require('../../../CallHandler');
-const dis = require("../../../dispatcher");
-const sdk = require('../../../index');
 import rate_limited_func from "../../../ratelimitedfunc";
 import * as Rooms from '../../../Rooms';
 import DMRoomMap from '../../../utils/DMRoomMap';
-const Receipt = require('../../../utils/Receipt');
 import TagOrderStore from '../../../stores/TagOrderStore';
 import RoomListStore from '../../../stores/RoomListStore';
 import CustomRoomTagStore from '../../../stores/CustomRoomTagStore';
 import GroupStore from '../../../stores/GroupStore';
 import RoomSubList from '../../structures/RoomSubList';
 import ResizeHandle from '../elements/ResizeHandle';
-
+import CallHandler from "../../../CallHandler";
+import dis from "../../../dispatcher";
+import * as sdk from "../../../index";
+import * as Receipt from "../../../utils/Receipt";
 import {Resizer} from '../../../resizer';
 import {Layout, Distributor} from '../../../resizer/distributors/roomsublist2';
+
 const HIDE_CONFERENCE_CHANS = true;
 const STANDARD_TAGS_REGEX = /^(m\.(favourite|lowpriority|server_notice)|im\.vector\.fake\.(invite|recent|direct|archived))$/;
 const HOVER_MOVE_TIMEOUT = 1000;
diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js
index 94e7e3172b..0789da2724 100644
--- a/src/components/views/rooms/RoomNameEditor.js
+++ b/src/components/views/rooms/RoomNameEditor.js
@@ -18,7 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-const sdk = require('../../../index');
+import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/SearchBar.js b/src/components/views/rooms/SearchBar.js
index 492c29a621..c9a9308544 100644
--- a/src/components/views/rooms/SearchBar.js
+++ b/src/components/views/rooms/SearchBar.js
@@ -16,8 +16,8 @@ limitations under the License.
 
 import React, {createRef} from 'react';
 import createReactClass from 'create-react-class';
-const classNames = require('classnames');
-const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
+import AccessibleButton from "../elements/AccessibleButton";
+import classNames from "classnames";
 import { _t } from '../../../languageHandler';
 
 module.exports = createReactClass({
diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js
index 006bd81c98..9fea1a3ad2 100644
--- a/src/components/views/rooms/UserTile.js
+++ b/src/components/views/rooms/UserTile.js
@@ -18,8 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as Avatar from '../../../Avatar';
-
-const sdk = require('../../../index');
+import * as sdk from "../../../index";
 
 module.exports = createReactClass({
     displayName: 'UserTile',
diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js
index 37a8b1a1dc..dc41e5e2c8 100644
--- a/src/components/views/settings/ChangePassword.js
+++ b/src/components/views/settings/ChangePassword.js
@@ -16,17 +16,15 @@ limitations under the License.
 */
 
 import Field from "../elements/Field";
-
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-const Modal = require("../../../Modal");
-const sdk = require("../../../index");
-
 import dis from "../../../dispatcher";
 import AccessibleButton from '../elements/AccessibleButton';
 import { _t } from '../../../languageHandler';
+import * as sdk from "../../../index";
+import Modal from "../../../Modal";
 
 import sessionStore from '../../../stores/SessionStore';
 
diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js
index 5f7d75c5c3..ec5f984d46 100644
--- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js
@@ -19,7 +19,7 @@ import {_t} from "../../../../../languageHandler";
 import PropTypes from "prop-types";
 import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
-const sdk = require("../../../../..");
+import * as sdk from "../../../../../index";
 
 export class LabsSettingToggle extends React.Component {
     static propTypes = {
diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
index 575221c780..7f3a2c401d 100644
--- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js
@@ -21,8 +21,7 @@ import {ListRule} from "../../../../../mjolnir/ListRule";
 import {BanList, RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList";
 import Modal from "../../../../../Modal";
 import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
-
-const sdk = require("../../../../..");
+import * as sdk from "../../../../../index";
 
 export default class MjolnirUserSettingsTab extends React.Component {
     constructor() {
diff --git a/src/components/views/settings/tabs/user/NotificationUserSettingsTab.js b/src/components/views/settings/tabs/user/NotificationUserSettingsTab.js
index 970659af6e..2e649cb7f8 100644
--- a/src/components/views/settings/tabs/user/NotificationUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/NotificationUserSettingsTab.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import {_t} from "../../../../../languageHandler";
-const sdk = require("../../../../..");
+import * as sdk from "../../../../../index";
 
 export default class NotificationUserSettingsTab extends React.Component {
     constructor() {
diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
index d0119ecbbf..f4fbcada3a 100644
--- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
@@ -21,8 +21,8 @@ import Field from "../../../elements/Field";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import {SettingLevel} from "../../../../../settings/SettingsStore";
 import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
-const Modal = require("../../../../../Modal");
-const sdk = require("../../../../..");
+import * as sdk from "../../../../../index";
+import Modal from "../../../../../Modal";
 
 export default class VoiceUserSettingsTab extends React.Component {
     constructor() {
diff --git a/src/dispatcher.js b/src/dispatcher.js
index 48c8dc86e9..5abdb29604 100644
--- a/src/dispatcher.js
+++ b/src/dispatcher.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 'use strict';
 
-const flux = require("flux");
+import flux from "flux";
 
 class MatrixDispatcher extends flux.Dispatcher {
     /**
diff --git a/src/utils/createMatrixClient.js b/src/utils/createMatrixClient.js
index dee9324460..c8ff35a584 100644
--- a/src/utils/createMatrixClient.js
+++ b/src/utils/createMatrixClient.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import Matrix from 'matrix-js-sdk';
+import * as Matrix from 'matrix-js-sdk';
 
 const localStorage = window.localStorage;
 
diff --git a/src/utils/permalinks/Permalinks.js b/src/utils/permalinks/Permalinks.js
index 591cdbb576..1174e59da6 100644
--- a/src/utils/permalinks/Permalinks.js
+++ b/src/utils/permalinks/Permalinks.js
@@ -21,8 +21,7 @@ import SpecPermalinkConstructor, {baseUrl as matrixtoBaseUrl} from "./SpecPermal
 import PermalinkConstructor, {PermalinkParts} from "./PermalinkConstructor";
 import RiotPermalinkConstructor from "./RiotPermalinkConstructor";
 import matrixLinkify from "../../linkify-matrix";
-
-const SdkConfig = require("../../SdkConfig");
+import SdkConfig from "../../SdkConfig";
 
 // The maximum number of servers to pick when working out which servers
 // to add to permalinks. The servers are appended as ?via=example.org

From 0d2cb6e73150b1a9255cff1d7ddda34fb900320e Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 14:43:06 -0700
Subject: [PATCH 38/86] Import haveTileForEvent() from the right place

---
 src/Unread.js                                  | 4 ++--
 src/components/structures/MessagePanel.js      | 4 ++--
 src/components/structures/RoomView.js          | 3 ++-
 src/components/structures/TimelinePanel.js     | 3 ++-
 src/components/views/rooms/SearchResultTile.js | 3 ++-
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/Unread.js b/src/Unread.js
index d199991dc5..f82c0899b5 100644
--- a/src/Unread.js
+++ b/src/Unread.js
@@ -17,6 +17,7 @@ limitations under the License.
 import {MatrixClientPeg} from "./MatrixClientPeg";
 import shouldHideEvent from './shouldHideEvent';
 import * as sdk from "./index";
+import {haveTileForEvent} from "./components/views/rooms/EventTile";
 
 /**
  * Returns true iff this event arriving in a room should affect the room's
@@ -38,8 +39,7 @@ export function eventTriggersUnreadCount(ev) {
     } else if (ev.getType() == 'm.room.server_acl') {
         return false;
     }
-    const EventTile = sdk.getComponent('rooms.EventTile');
-    return EventTile.haveTileForEvent(ev);
+    return haveTileForEvent(ev);
 }
 
 export function doesRoomHaveUnreadMessages(room) {
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index 54b910732a..4ad75eb700 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -27,6 +27,7 @@ import * as sdk from '../../index';
 import {MatrixClientPeg} from '../../MatrixClientPeg';
 import SettingsStore from '../../settings/SettingsStore';
 import {_t} from "../../languageHandler";
+import {haveTileForEvent} from "../views/rooms/EventTile";
 
 const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
 const continuedTypes = ['m.sticker', 'm.room.message'];
@@ -318,8 +319,7 @@ export default class MessagePanel extends React.Component {
             return true;
         }
 
-        const EventTile = sdk.getComponent('rooms.EventTile');
-        if (!EventTile.haveTileForEvent(mxEv)) {
+        if (!haveTileForEvent(mxEv)) {
             return false; // no tile = no show
         }
 
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 1cb9e7db5e..d3309a1f43 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -55,6 +55,7 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
 import WidgetUtils from '../../utils/WidgetUtils';
 import AccessibleButton from "../views/elements/AccessibleButton";
 import RightPanelStore from "../../stores/RightPanelStore";
+import {haveTileForEvent} from "../views/rooms/EventTile";
 
 const DEBUG = false;
 let debuglog = function() {};
@@ -1245,7 +1246,7 @@ export default createReactClass({
             const roomId = mxEv.getRoomId();
             const room = cli.getRoom(roomId);
 
-            if (!EventTile.haveTileForEvent(mxEv)) {
+            if (!haveTileForEvent(mxEv)) {
                 // XXX: can this ever happen? It will make the result count
                 // not match the displayed count.
                 continue;
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 54539b63fb..06be5af41c 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -35,6 +35,7 @@ import { KeyCode } from '../../Keyboard';
 import Timer from '../../utils/Timer';
 import shouldHideEvent from '../../shouldHideEvent';
 import EditorStateTransfer from '../../utils/EditorStateTransfer';
+import {haveTileForEvent} from "../views/rooms/EventTile";
 
 const PAGINATE_SIZE = 20;
 const INITIAL_SIZE = 20;
@@ -1179,7 +1180,7 @@ const TimelinePanel = createReactClass({
 
             const shouldIgnore = !!ev.status || // local echo
                 (ignoreOwn && ev.sender && ev.sender.userId == myUserId);   // own message
-            const isWithoutTile = !EventTile.haveTileForEvent(ev) || shouldHideEvent(ev);
+            const isWithoutTile = !haveTileForEvent(ev) || shouldHideEvent(ev);
 
             if (isWithoutTile || !node) {
                 // don't start counting if the event should be ignored,
diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js
index bf34a56de3..57856a3a5b 100644
--- a/src/components/views/rooms/SearchResultTile.js
+++ b/src/components/views/rooms/SearchResultTile.js
@@ -19,6 +19,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import * as sdk from '../../../index';
+import {haveTileForEvent} from "./EventTile";
 
 export default createReactClass({
     displayName: 'SearchResult',
@@ -54,7 +55,7 @@ export default createReactClass({
             if (!contextual) {
                 highlights = this.props.searchHighlights;
             }
-            if (EventTile.haveTileForEvent(ev)) {
+            if (haveTileForEvent(ev)) {
                 ret.push(<EventTile key={eventId+"+"+j} mxEvent={ev} contextual={contextual} highlights={highlights}
                           permalinkCreator={this.props.permalinkCreator}
                           highlightLink={this.props.resultLink}

From 615648af13e046ee50151a23fffeaf0bb65776d6 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sun, 22 Dec 2019 19:47:10 -0700
Subject: [PATCH 39/86] Fix tabbed view export for component index

---
 src/components/structures/TabbedView.js            | 2 +-
 src/components/views/dialogs/RoomSettingsDialog.js | 2 +-
 src/components/views/dialogs/UserSettingsDialog.js | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js
index ae5f9e3ee1..20af183af8 100644
--- a/src/components/structures/TabbedView.js
+++ b/src/components/structures/TabbedView.js
@@ -38,7 +38,7 @@ export class Tab {
     }
 }
 
-export class TabbedView extends React.Component {
+export default class TabbedView extends React.Component {
     static propTypes = {
         // The tabs to show
         tabs: PropTypes.arrayOf(PropTypes.instanceOf(Tab)).isRequired,
diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js
index 67b30e19c8..2f01204c84 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.js
+++ b/src/components/views/dialogs/RoomSettingsDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import {Tab, TabbedView} from "../../structures/TabbedView";
+import TabbedView, {Tab} from "../../structures/TabbedView";
 import {_t, _td} from "../../../languageHandler";
 import AdvancedRoomSettingsTab from "../settings/tabs/room/AdvancedRoomSettingsTab";
 import RolesRoomSettingsTab from "../settings/tabs/room/RolesRoomSettingsTab";
diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js
index a3f586cdea..b135d5f5f6 100644
--- a/src/components/views/dialogs/UserSettingsDialog.js
+++ b/src/components/views/dialogs/UserSettingsDialog.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import {Tab, TabbedView} from "../../structures/TabbedView";
+import TabbedView, {Tab} from "../../structures/TabbedView";
 import {_t, _td} from "../../../languageHandler";
 import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab";
 import SettingsStore from "../../../settings/SettingsStore";

From 18ac2db2ea5c44de4153efbf133b8085ba613075 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 14:47:49 -0700
Subject: [PATCH 40/86] Fix Notifier imports in NotificationControllers

require() is a bit weird for riot-web's webpack, so we fork it out to its own function to reduce the weirdness.

The added weirdness is that require() is sync though exports a module instead. If we use import(), we get a promise which doesn't help us here. We therefore have to require() and pull out the default export, though this is only a problem for webpack - babel (our chosen compiler for exporting ES6) doesn't need this, hence the if statement.
---
 .../controllers/NotificationControllers.js    | 21 ++++++++++---------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/settings/controllers/NotificationControllers.js b/src/settings/controllers/NotificationControllers.js
index ada4155206..395da765a1 100644
--- a/src/settings/controllers/NotificationControllers.js
+++ b/src/settings/controllers/NotificationControllers.js
@@ -34,10 +34,15 @@ function isMasterRuleEnabled() {
     return !masterRule.enabled;
 }
 
+function getNotifier() {
+    let Notifier = require('../../Notifier'); // avoids cyclical references
+    if (Notifier.default) Notifier = Notifier.default; // correct for webpack require() weirdness
+    return Notifier;
+}
+
 export class NotificationsEnabledController extends SettingController {
     getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
-        const Notifier = require('../../Notifier'); // avoids cyclical references
-        if (!Notifier.isPossible()) return false;
+        if (!getNotifier().isPossible()) return false;
 
         if (calculatedValue === null || calculatedAtLevel === "default") {
             return isMasterRuleEnabled();
@@ -47,18 +52,15 @@ export class NotificationsEnabledController extends SettingController {
     }
 
     onChange(level, roomId, newValue) {
-        const Notifier = require('../../Notifier'); // avoids cyclical references
-
-        if (Notifier.supportsDesktopNotifications()) {
-            Notifier.setEnabled(newValue);
+        if (getNotifier().supportsDesktopNotifications()) {
+            getNotifier().setEnabled(newValue);
         }
     }
 }
 
 export class NotificationBodyEnabledController extends SettingController {
     getValueOverride(level, roomId, calculatedValue) {
-        const Notifier = require('../../Notifier'); // avoids cyclical references
-        if (!Notifier.isPossible()) return false;
+        if (!getNotifier().isPossible()) return false;
 
         if (calculatedValue === null) {
             return isMasterRuleEnabled();
@@ -70,8 +72,7 @@ export class NotificationBodyEnabledController extends SettingController {
 
 export class AudioNotificationsEnabledController extends SettingController {
     getValueOverride(level, roomId, calculatedValue) {
-        const Notifier = require('../../Notifier'); // avoids cyclical references
-        if (!Notifier.isPossible()) return false;
+        if (!getNotifier().isPossible()) return false;
 
         // Note: Audio notifications are *not* enabled by default.
         return calculatedValue;

From 539a33c722997b22e1dbfe95eb98eaae1b45a81d Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:02:36 -0700
Subject: [PATCH 41/86] Fix naming conflict in VectorConferenceHandler

---
 src/VectorConferenceHandler.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/VectorConferenceHandler.js b/src/VectorConferenceHandler.js
index d0120136e1..180dad876b 100644
--- a/src/VectorConferenceHandler.js
+++ b/src/VectorConferenceHandler.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import {createNewMatrixCall, Room} from "matrix-js-sdk";
+import {createNewMatrixCall as jsCreateNewMatrixCall, Room} from "matrix-js-sdk";
 import CallHandler from './CallHandler';
 import {MatrixClientPeg} from "./MatrixClientPeg";
 
@@ -43,7 +43,7 @@ ConferenceCall.prototype.setup = function() {
         // return a call for *this* room to be placed. We also tack on
         // confUserId to speed up lookups (else we'd need to loop every room
         // looking for a 1:1 room with this conf user ID!)
-        const call = createNewMatrixCall(self.client, room.roomId);
+        const call = jsCreateNewMatrixCall(self.client, room.roomId);
         call.confUserId = self.confUserId;
         call.groupRoomId = self.groupRoomId;
         return call;

From d8da634c8b811a9cde47f44dc74fa0ffc2f0701e Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:01:43 -0700
Subject: [PATCH 42/86] Cosmetic updates to package.json

---
 package.json | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/package.json b/package.json
index 99e4983d60..2899d9fdb7 100644
--- a/package.json
+++ b/package.json
@@ -9,27 +9,25 @@
   },
   "license": "Apache-2.0",
   "files": [
+    "lib",
+    "res",
+    "src",
+    "scripts",
+    "git-revision.txt",
+    "header",
     "CHANGELOG.md",
     "CONTRIBUTING.rst",
     "LICENSE",
     "README.md",
-    "code_style.md",
-    "git-revision.txt",
-    "header",
-    "lib",
-    "package.json",
-    "scripts",
-    "docs",
-    "src",
-    "res"
+    "package.json"
   ],
   "bin": {
     "reskindex": "scripts/reskindex.js",
     "matrix-gen-i18n": "scripts/gen-i18n.js",
     "matrix-prune-i18n": "scripts/prune-i18n.js"
   },
-  "main": "lib/index.js",
-  "typings": "lib/index.d.ts",
+  "main": "./lib/index.js",
+  "typings": "./lib/index.d.ts",
   "scripts": {
     "i18n": "matrix-gen-i18n",
     "prunei18n": "matrix-prune-i18n",
@@ -40,7 +38,7 @@
     "rethemendex": "res/css/rethemendex.sh",
     "clean": "rimraf lib",
     "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
-    "build:compile": "yarn reskindex && babel src -s -d lib --verbose --extensions \".ts,.js\"",
+    "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js\" src",
     "build:types": "tsc --emitDeclarationOnly",
     "start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all",
     "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",

From 69424f4b4286fb2d6e6358d6aebe7c9e20639500 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 19:08:18 -0700
Subject: [PATCH 43/86] Add package.json fields for riot-web's webpack

See https://github.com/vector-im/riot-web/commit/a1c9551bc8a1a6d61afed7e87ff7cebb3042a5ac
---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 2899d9fdb7..3104ab1ac4 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
   },
   "main": "./lib/index.js",
   "typings": "./lib/index.d.ts",
+  "matrix_src_main": "./src/index.js",
   "scripts": {
     "i18n": "matrix-gen-i18n",
     "prunei18n": "matrix-prune-i18n",

From 23e533393546d9f16b8ff6e1de65e1e0ae27f522 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:02:25 -0700
Subject: [PATCH 44/86] Introduce babel's export-default-from plugin to fix
 build errors

We do a lot of default exporting, so we kinda need this. It even asks for it to be installed when it is missing.
---
 .babelrc     |  1 +
 package.json |  1 +
 yarn.lock    | 15 +++++++++++++++
 3 files changed, 17 insertions(+)

diff --git a/.babelrc b/.babelrc
index af736e9c19..f75a9f82ef 100644
--- a/.babelrc
+++ b/.babelrc
@@ -15,6 +15,7 @@
     ],
     "plugins": [
         ["@babel/plugin-proposal-decorators", { "legacy": true }],
+        "@babel/plugin-proposal-export-default-from",
         "@babel/plugin-proposal-numeric-separator",
         "@babel/plugin-proposal-class-properties",
         "@babel/plugin-proposal-object-rest-spread",
diff --git a/package.json b/package.json
index 99e4983d60..54f4534762 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,7 @@
     "@babel/core": "^7.7.5",
     "@babel/plugin-proposal-class-properties": "^7.7.4",
     "@babel/plugin-proposal-decorators": "^7.7.4",
+    "@babel/plugin-proposal-export-default-from": "^7.7.4",
     "@babel/plugin-proposal-numeric-separator": "^7.7.4",
     "@babel/plugin-proposal-object-rest-spread": "^7.7.4",
     "@babel/plugin-transform-flow-comments": "^7.7.4",
diff --git a/yarn.lock b/yarn.lock
index 4e1be061bc..3dba7da904 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -320,6 +320,14 @@
     "@babel/helper-plugin-utils" "^7.0.0"
     "@babel/plugin-syntax-dynamic-import" "^7.7.4"
 
+"@babel/plugin-proposal-export-default-from@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.7.4.tgz#890de3c0c475374638292df31f6582160b54d639"
+  integrity sha512-1t6dh7BHYUz4zD1m4pozYYEZy/3m8dgOr9owx3r0mPPI3iGKRUKUbIxfYmcJ4hwljs/dhd0qOTr1ZDUp43ix+w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-export-default-from" "^7.7.4"
+
 "@babel/plugin-proposal-json-strings@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d"
@@ -381,6 +389,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
+"@babel/plugin-syntax-export-default-from@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.7.4.tgz#897f05808298060b52873fa804ff853540790ea1"
+  integrity sha512-j888jpjATLEzOWhKawq46UrpXnCRDbdhBd5io4jgwjJ3+CHHGCRb6PNAVEgs+BXIb+dNRAmnkv36zfB992PRVw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
 "@babel/plugin-syntax-flow@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b"

From cfa21cbb8cb46fd959dc8bf54c1844da7c87b269 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 19 Dec 2019 18:29:22 -0700
Subject: [PATCH 45/86] Define getLanguageFromBrowser() for LanguageDropdown

Without it we can't compile, so we should define it. It looks like it's never been defined, and LanguageDropdown seems to use it as a last resort - it should be safe to land.
---
 src/languageHandler.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/languageHandler.js b/src/languageHandler.js
index c56e5378df..c11f26ddf1 100644
--- a/src/languageHandler.js
+++ b/src/languageHandler.js
@@ -336,6 +336,10 @@ export function getLanguagesFromBrowser() {
     return [navigator.userLanguage || "en"];
 }
 
+export function getLanguageFromBrowser() {
+    return getLanguagesFromBrowser()[0];
+}
+
 /**
  * Turns a language string, normalises it,
  * (see normalizeLanguageKey) into an array of language strings

From 56adb8244b2c80703dad6341805e4f0e1e770b4b Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 13:58:37 -0700
Subject: [PATCH 46/86] Add a bit of debugging to incorrect components in the
 Skinner

---
 src/Skinner.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Skinner.js b/src/Skinner.js
index 7235d55937..06855691bd 100644
--- a/src/Skinner.js
+++ b/src/Skinner.js
@@ -58,7 +58,7 @@ class Skinner {
         // components have to be functions.
         const validType = typeof comp === 'function';
         if (!validType) {
-            throw new Error(`Not a valid component: ${name}.`);
+            throw new Error(`Not a valid component: ${name} (type = ${typeof(comp)}).`);
         }
         return comp;
     }

From 3eb3be45d18e6292c7bbddcae8cb1942d3a7b8a4 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 20 Dec 2019 13:58:46 -0700
Subject: [PATCH 47/86] Fix import of language index

This is a similar fix to https://github.com/matrix-org/matrix-react-sdk/pull/3766/commits/18ac2db2ea5c44de4153efbf133b8085ba613075
---
 src/languageHandler.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/languageHandler.js b/src/languageHandler.js
index c56e5378df..4aa22f3e65 100644
--- a/src/languageHandler.js
+++ b/src/languageHandler.js
@@ -410,11 +410,12 @@ export function pickBestLanguage(langs) {
 }
 
 function getLangsJson() {
-    return new Promise((resolve, reject) => {
+    return new Promise(async (resolve, reject) => {
         let url;
         try {
             // $webapp is a webpack resolve alias pointing to the output directory, see webpack config
-            url = require('$webapp/i18n/languages.json');
+            url = import('$webapp/i18n/languages.json');
+            if (url.then) url = (await url).default; // webpack resolves to a Module through a promise.
         } catch (e) {
             url = i18nFolder + 'languages.json';
         }

From 9edc361afc283961be02abc7b139a66e062d5ad5 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 3 Jan 2020 12:29:22 -0700
Subject: [PATCH 48/86] Use new imports for js-sdk's ContentRepo

Per https://github.com/matrix-org/matrix-js-sdk/pull/1134/commits/f4d1c5c006027962cd18dffb3f7c521d9e24e831
---
 src/Avatar.js                               | 4 ++--
 src/components/structures/RoomDirectory.js  | 4 ++--
 src/components/views/avatars/RoomAvatar.js  | 4 ++--
 src/components/views/rooms/RoomDetailRow.js | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/Avatar.js b/src/Avatar.js
index 6d31959718..1039ab1bb1 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -15,9 +15,9 @@ limitations under the License.
 */
 
 'use strict';
-import {ContentRepo} from 'matrix-js-sdk';
 import {MatrixClientPeg} from './MatrixClientPeg';
 import DMRoomMap from './utils/DMRoomMap';
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 export function avatarUrlForMember(member, width, height, resizeMethod) {
     let url = member.getAvatarUrl(
@@ -38,7 +38,7 @@ export function avatarUrlForMember(member, width, height, resizeMethod) {
 }
 
 export function avatarUrlForUser(user, width, height, resizeMethod) {
-    const url = ContentRepo.getHttpUriForMxc(
+    const url = getHttpUriForMxc(
         MatrixClientPeg.get().getHomeserverUrl(), user.avatarUrl,
         Math.floor(width * window.devicePixelRatio),
         Math.floor(height * window.devicePixelRatio),
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index e06c00902b..d783c8cc3f 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -18,7 +18,6 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-import {ContentRepo} from "matrix-js-sdk";
 import {MatrixClientPeg} from "../../MatrixClientPeg";
 import * as sdk from "../../index";
 import dis from "../../dispatcher";
@@ -28,6 +27,7 @@ import PropTypes from 'prop-types';
 import { _t } from '../../languageHandler';
 import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
 import Analytics from '../../Analytics';
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 const MAX_NAME_LENGTH = 80;
 const MAX_TOPIC_LENGTH = 160;
@@ -463,7 +463,7 @@ export default createReactClass({
             topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`;
         }
         topic = linkifyAndSanitizeHtml(topic);
-        const avatarUrl = ContentRepo.getHttpUriForMxc(
+        const avatarUrl = getHttpUriForMxc(
                                 MatrixClientPeg.get().getHomeserverUrl(),
                                 room.avatar_url, 32, 32, "crop",
                             );
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index 3b51fae4b3..c79e1827da 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -16,11 +16,11 @@ limitations under the License.
 import React from "react";
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-import {ContentRepo} from "matrix-js-sdk";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
 import * as sdk from "../../../index";
 import * as Avatar from '../../../Avatar';
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 export default createReactClass({
     displayName: 'RoomAvatar',
@@ -82,7 +82,7 @@ export default createReactClass({
 
     getImageUrls: function(props) {
         return [
-            ContentRepo.getHttpUriForMxc(
+            getHttpUriForMxc(
                 MatrixClientPeg.get().getHomeserverUrl(),
                 props.oobData.avatarUrl,
                 Math.floor(props.width * window.devicePixelRatio),
diff --git a/src/components/views/rooms/RoomDetailRow.js b/src/components/views/rooms/RoomDetailRow.js
index 66ec733061..2210406c18 100644
--- a/src/components/views/rooms/RoomDetailRow.js
+++ b/src/components/views/rooms/RoomDetailRow.js
@@ -18,10 +18,10 @@ import * as sdk from '../../../index';
 import React, {createRef} from 'react';
 import { _t } from '../../../languageHandler';
 import { linkifyElement } from '../../../HtmlUtils';
-import { ContentRepo } from 'matrix-js-sdk';
 import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 export function getDisplayAliasForRoom(room) {
     return room.canonicalAlias || (room.aliases ? room.aliases[0] : "");
@@ -101,7 +101,7 @@ export default createReactClass({
             <td className="mx_RoomDirectory_roomAvatar">
                 <BaseAvatar width={24} height={24} resizeMethod='crop'
                     name={name} idName={name}
-                    url={ContentRepo.getHttpUriForMxc(
+                    url={getHttpUriForMxc(
                             MatrixClientPeg.get().getHomeserverUrl(),
                             room.avatarUrl, 24, 24, "crop")} />
             </td>

From 206d4c78d2a3c943fd3d1ab6980061e4fb38a1ce Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 3 Jan 2020 12:32:29 -0700
Subject: [PATCH 49/86] Fix references to 'this' in Avatar and Unread

---
 src/Avatar.js | 2 +-
 src/Unread.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Avatar.js b/src/Avatar.js
index 3377849eca..70be0a4684 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -32,7 +32,7 @@ export function avatarUrlForMember(member, width, height, resizeMethod) {
         // member can be null here currently since on invites, the JS SDK
         // does not have enough info to build a RoomMember object for
         // the inviter.
-        url = this.defaultAvatarUrlForString(member ? member.userId : '');
+        url = defaultAvatarUrlForString(member ? member.userId : '');
     }
     return url;
 }
diff --git a/src/Unread.js b/src/Unread.js
index c2eaa468f5..dba8be492d 100644
--- a/src/Unread.js
+++ b/src/Unread.js
@@ -77,7 +77,7 @@ export function doesRoomHaveUnreadMessages(room) {
             // that counts and we can stop looking because the user's read
             // this and everything before.
             return false;
-        } else if (!shouldHideEvent(ev) && this.eventTriggersUnreadCount(ev)) {
+        } else if (!shouldHideEvent(ev) && eventTriggersUnreadCount(ev)) {
             // We've found a message that counts before we hit
             // the user's read receipt, so this room is definitely unread.
             return true;

From 9213f88180ebb7109fe416efca485242c7c7fb89 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 15:13:42 -0700
Subject: [PATCH 50/86] Re-add docs

---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 3104ab1ac4..221155f70f 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
     "src",
     "scripts",
     "git-revision.txt",
+    "docs",
     "header",
     "CHANGELOG.md",
     "CONTRIBUTING.rst",

From 4e4871c281655dff5cecf75c8d085e3cd487d2f9 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 13:56:14 -0700
Subject: [PATCH 51/86] Move lang import to the top of the file

---
 src/languageHandler.js | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/languageHandler.js b/src/languageHandler.js
index c31db5eb5b..3a061df915 100644
--- a/src/languageHandler.js
+++ b/src/languageHandler.js
@@ -22,6 +22,9 @@ import counterpart from 'counterpart';
 import React from 'react';
 import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
 
+// $webapp is a webpack resolve alias pointing to the output directory, see webpack config
+import webpackLangJsonUrl from "$webapp/i18n/languages.json";
+
 const i18nFolder = 'i18n/';
 
 // Control whether to also return original, untranslated strings
@@ -417,9 +420,7 @@ function getLangsJson() {
     return new Promise(async (resolve, reject) => {
         let url;
         try {
-            // $webapp is a webpack resolve alias pointing to the output directory, see webpack config
-            url = import('$webapp/i18n/languages.json');
-            if (url.then) url = (await url).default; // webpack resolves to a Module through a promise.
+            url = webpackLangJsonUrl;
         } catch (e) {
             url = i18nFolder + 'languages.json';
         }

From a0da13200f4931b0620fcd9c6dc826dcab8787cd Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 15:52:46 -0700
Subject: [PATCH 52/86] Fix conflicts in package.json

We removed the emojistrip script
---
 package.json | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/package.json b/package.json
index 7c5fbe656f..b876106891 100644
--- a/package.json
+++ b/package.json
@@ -34,22 +34,9 @@
     "i18n": "matrix-gen-i18n",
     "prunei18n": "matrix-prune-i18n",
     "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
-<<<<<<< HEAD
-    "emoji-data-strip": "node scripts/emoji-data-strip.js",
     "reskindex": "node scripts/reskindex.js -h header",
     "reskindex:watch": "node scripts/reskindex.js -h header -w",
     "rethemendex": "res/css/rethemendex.sh",
-=======
-    "build": "yarn reskindex && yarn start:init",
-    "build:watch": "babel src -w --skip-initial-build -d lib --source-maps --copy-files",
-    "start": "yarn start:init && yarn start:all",
-    "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn build:watch\" \"yarn reskindex:watch\"",
-    "start:init": "babel src -d lib --source-maps --copy-files",
-    "lint": "eslint src/",
-    "lintall": "eslint src/ test/",
-    "lintwithexclusions": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
-    "stylelint": "stylelint 'res/css/**/*.scss'",
->>>>>>> develop
     "clean": "rimraf lib",
     "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
     "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js\" src",

From 3e5cc9550b4e4dcd052a189d33835c548535c1e6 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 14:15:38 -0700
Subject: [PATCH 53/86] Fix import merge conflicts, removing any that aren't
 needed anymore

Many imports were removed as part of refactoring work, so here we are.
---
 .../views/dialogs/EncryptedEventDialog.js        | 16 +++-------------
 .../dialogs/keybackup/CreateKeyBackupDialog.js   |  6 ------
 src/components/structures/EmbeddedPage.js        |  5 -----
 src/components/structures/LeftPanel.js           |  5 -----
 src/components/structures/MyGroups.js            |  6 ------
 src/components/structures/RoomDirectory.js       |  4 ----
 src/components/structures/RoomView.js            |  3 ---
 src/components/structures/TimelinePanel.js       | 11 +----------
 src/components/views/avatars/BaseAvatar.js       |  5 -----
 src/components/views/dialogs/DevtoolsDialog.js   |  8 --------
 .../views/dialogs/RoomSettingsDialog.js          |  7 +------
 .../dialogs/keybackup/RestoreKeyBackupDialog.js  |  6 ------
 src/components/views/elements/ImageView.js       |  3 ---
 src/components/views/elements/TagTile.js         |  5 -----
 src/components/views/groups/GroupInviteTile.js   |  5 -----
 src/components/views/groups/GroupMemberTile.js   |  5 -----
 src/components/views/groups/GroupRoomTile.js     |  5 -----
 src/components/views/groups/GroupUserSettings.js |  5 -----
 .../views/room_settings/AliasSettings.js         | 10 ----------
 .../views/room_settings/RelatedGroupSettings.js  |  7 +------
 src/components/views/rooms/EventTile.js          | 13 -------------
 src/components/views/rooms/LinkPreviewWidget.js  |  3 ---
 src/components/views/rooms/MemberInfo.js         |  5 -----
 src/components/views/settings/KeyBackupPanel.js  |  5 -----
 .../settings/tabs/room/GeneralRoomSettingsTab.js |  5 -----
 .../settings/tabs/user/FlairUserSettingsTab.js   |  6 ------
 26 files changed, 6 insertions(+), 158 deletions(-)

diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index 28dd802082..f6e17b1c84 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -14,28 +14,18 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-<<<<<<< HEAD
 import React from "react";
-=======
-import {Key} from "../../../Keyboard";
-
-const React = require("react");
->>>>>>> develop
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
+import {Key} from "../../../Keyboard";
+import * as sdk from "../../../index";
 
-const sdk = require('../../../index');
-
-<<<<<<< HEAD
-export default createReactClass({
-=======
 // XXX: This component is not cross-signing aware.
 // https://github.com/vector-im/riot-web/issues/11752 tracks either updating this
 // component or taking it out to pasture.
-module.exports = createReactClass({
->>>>>>> develop
+export default createReactClass({
     displayName: 'EncryptedEventDialog',
 
     propTypes: {
diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
index af07ce3fb7..8940239cfd 100644
--- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
+++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js
@@ -17,15 +17,9 @@ limitations under the License.
 
 import React from 'react';
 import FileSaver from 'file-saver';
-<<<<<<< HEAD
 import * as sdk from '../../../../index';
 import {MatrixClientPeg} from '../../../../MatrixClientPeg';
-=======
 import PropTypes from 'prop-types';
-
-import sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
->>>>>>> develop
 import { scorePassword } from '../../../../utils/PasswordScorer';
 import { _t } from '../../../../languageHandler';
 import { accessSecretStorage } from '../../../../CrossSigningManager';
diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index 276baccef1..6d734c3838 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -25,12 +25,7 @@ import { _t } from '../../languageHandler';
 import sanitizeHtml from 'sanitize-html';
 import * as sdk from '../../index';
 import dis from '../../dispatcher';
-<<<<<<< HEAD
 import {MatrixClientPeg} from '../../MatrixClientPeg';
-import { MatrixClient } from 'matrix-js-sdk';
-=======
-import MatrixClientPeg from '../../MatrixClientPeg';
->>>>>>> develop
 import classnames from 'classnames';
 import MatrixClientContext from "../../contexts/MatrixClientContext";
 
diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js
index ec52afba19..8a7d10e5b5 100644
--- a/src/components/structures/LeftPanel.js
+++ b/src/components/structures/LeftPanel.js
@@ -22,12 +22,7 @@ import classNames from 'classnames';
 import { Key } from '../../Keyboard';
 import * as sdk from '../../index';
 import dis from '../../dispatcher';
-<<<<<<< HEAD
 import * as VectorConferenceHandler from '../../VectorConferenceHandler';
-import TagPanelButtons from './TagPanelButtons';
-=======
-import VectorConferenceHandler from '../../VectorConferenceHandler';
->>>>>>> develop
 import SettingsStore from '../../settings/SettingsStore';
 import {_t} from "../../languageHandler";
 import Analytics from "../../Analytics";
diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js
index 7d7b19d979..b26ab5ff70 100644
--- a/src/components/structures/MyGroups.js
+++ b/src/components/structures/MyGroups.js
@@ -17,13 +17,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
-import PropTypes from 'prop-types';
-import { MatrixClient } from 'matrix-js-sdk';
 import * as sdk from '../../index';
-=======
-import sdk from '../../index';
->>>>>>> develop
 import { _t } from '../../languageHandler';
 import dis from '../../dispatcher';
 import AccessibleButton from '../views/elements/AccessibleButton';
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index 87b9d076e2..42dbc1b4e4 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -27,11 +27,7 @@ import PropTypes from 'prop-types';
 import { _t } from '../../languageHandler';
 import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
 import Analytics from '../../Analytics';
-<<<<<<< HEAD
 import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
-=======
-import MatrixClientContext from "../../contexts/MatrixClientContext";
->>>>>>> develop
 
 const MAX_NAME_LENGTH = 80;
 const MAX_TOPIC_LENGTH = 160;
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 83ef6441f6..3c311d2b83 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -53,11 +53,8 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
 import WidgetUtils from '../../utils/WidgetUtils';
 import AccessibleButton from "../views/elements/AccessibleButton";
 import RightPanelStore from "../../stores/RightPanelStore";
-<<<<<<< HEAD
 import {haveTileForEvent} from "../views/rooms/EventTile";
-=======
 import RoomContext from "../../contexts/RoomContext";
->>>>>>> develop
 
 const DEBUG = false;
 let debuglog = function() {};
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index ceb4113d86..1d50a51579 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -25,22 +25,13 @@ import PropTypes from 'prop-types';
 import {EventTimeline} from "matrix-js-sdk";
 import * as Matrix from "matrix-js-sdk";
 import { _t } from '../../languageHandler';
-<<<<<<< HEAD
 import {MatrixClientPeg} from "../../MatrixClientPeg";
 import * as ObjectUtils from "../../ObjectUtils";
 import UserActivity from "../../UserActivity";
 import Modal from "../../Modal";
 import dis from "../../dispatcher";
 import * as sdk from "../../index";
-import { KeyCode } from '../../Keyboard';
-=======
-const MatrixClientPeg = require("../../MatrixClientPeg");
-const dis = require("../../dispatcher");
-const ObjectUtils = require('../../ObjectUtils');
-const Modal = require("../../Modal");
-const UserActivity = require("../../UserActivity");
-import {Key} from '../../Keyboard';
->>>>>>> develop
+import { Key } from '../../Keyboard';
 import Timer from '../../utils/Timer';
 import shouldHideEvent from '../../shouldHideEvent';
 import EditorStateTransfer from '../../utils/EditorStateTransfer';
diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js
index 2b49916bbe..4c34cee853 100644
--- a/src/components/views/avatars/BaseAvatar.js
+++ b/src/components/views/avatars/BaseAvatar.js
@@ -20,12 +20,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
-import { MatrixClient } from 'matrix-js-sdk';
 import * as AvatarLogic from '../../../Avatar';
-=======
-import AvatarLogic from '../../../Avatar';
->>>>>>> develop
 import SettingsStore from "../../../settings/SettingsStore";
 import AccessibleButton from '../elements/AccessibleButton';
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js
index 1db6e9b284..34b2f5a52b 100644
--- a/src/components/views/dialogs/DevtoolsDialog.js
+++ b/src/components/views/dialogs/DevtoolsDialog.js
@@ -16,18 +16,10 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-<<<<<<< HEAD
 import * as sdk from '../../../index';
 import SyntaxHighlight from '../elements/SyntaxHighlight';
 import { _t } from '../../../languageHandler';
-import {MatrixClientPeg} from '../../../MatrixClientPeg';
-=======
 import { Room } from "matrix-js-sdk";
-
-import sdk from '../../../index';
-import SyntaxHighlight from '../elements/SyntaxHighlight';
-import { _t } from '../../../languageHandler';
->>>>>>> develop
 import Field from "../elements/Field";
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
 
diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js
index 0adcfb441f..a99141870b 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.js
+++ b/src/components/views/dialogs/RoomSettingsDialog.js
@@ -24,14 +24,9 @@ import RolesRoomSettingsTab from "../settings/tabs/room/RolesRoomSettingsTab";
 import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab";
 import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
 import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
-<<<<<<< HEAD
+import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
 import * as sdk from "../../../index";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-=======
-import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
-import sdk from "../../../index";
-import MatrixClientPeg from "../../../MatrixClientPeg";
->>>>>>> develop
 import dis from "../../../dispatcher";
 import SettingsStore from "../../../settings/SettingsStore";
 
diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
index 7a0e48263e..77fdee5e8a 100644
--- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
+++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js
@@ -16,15 +16,9 @@ limitations under the License.
 */
 
 import React from 'react';
-<<<<<<< HEAD
 import * as sdk from '../../../../index';
 import {MatrixClientPeg} from '../../../../MatrixClientPeg';
-=======
 import { MatrixClient } from 'matrix-js-sdk';
-
-import sdk from '../../../../index';
-import MatrixClientPeg from '../../../../MatrixClientPeg';
->>>>>>> develop
 import Modal from '../../../../Modal';
 import { _t } from '../../../../languageHandler';
 import {Key} from "../../../../Keyboard";
diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js
index 449eaad7a7..7cc2741df7 100644
--- a/src/components/views/elements/ImageView.js
+++ b/src/components/views/elements/ImageView.js
@@ -22,14 +22,11 @@ import PropTypes from 'prop-types';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {formatDate} from '../../../DateUtils';
 import { _t } from '../../../languageHandler';
-<<<<<<< HEAD
 import filesize from "filesize";
 import AccessibleButton from "./AccessibleButton";
 import Modal from "../../../Modal";
 import * as sdk from "../../../index";
-=======
 import {Key} from "../../../Keyboard";
->>>>>>> develop
 
 export default class ImageView extends React.Component {
     static propTypes = {
diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js
index d4a9d836aa..2f182c261e 100644
--- a/src/components/views/elements/TagTile.js
+++ b/src/components/views/elements/TagTile.js
@@ -20,12 +20,7 @@ import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from 'classnames';
-<<<<<<< HEAD
-import { MatrixClient } from 'matrix-js-sdk';
 import * as sdk from '../../../index';
-=======
-import sdk from '../../../index';
->>>>>>> develop
 import dis from '../../../dispatcher';
 import { isOnlyCtrlOrCmdIgnoreShiftKeyEvent } from '../../../Keyboard';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js
index 64aadf406d..808cf17d55 100644
--- a/src/components/views/groups/GroupInviteTile.js
+++ b/src/components/views/groups/GroupInviteTile.js
@@ -19,12 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
-import { MatrixClient } from 'matrix-js-sdk';
 import * as sdk from '../../../index';
-=======
-import sdk from '../../../index';
->>>>>>> develop
 import dis from '../../../dispatcher';
 import {_t} from '../../../languageHandler';
 import classNames from 'classnames';
diff --git a/src/components/views/groups/GroupMemberTile.js b/src/components/views/groups/GroupMemberTile.js
index 2049e7d6bf..68513cf0db 100644
--- a/src/components/views/groups/GroupMemberTile.js
+++ b/src/components/views/groups/GroupMemberTile.js
@@ -19,12 +19,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
-import { MatrixClient } from 'matrix-js-sdk';
 import * as sdk from '../../../index';
-=======
-import sdk from '../../../index';
->>>>>>> develop
 import dis from '../../../dispatcher';
 import { GroupMemberType } from '../../../groups';
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js
index 6a9c189e09..94d143b263 100644
--- a/src/components/views/groups/GroupRoomTile.js
+++ b/src/components/views/groups/GroupRoomTile.js
@@ -17,12 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
-import {MatrixClient} from 'matrix-js-sdk';
 import * as sdk from '../../../index';
-=======
-import sdk from '../../../index';
->>>>>>> develop
 import dis from '../../../dispatcher';
 import { GroupRoomType } from '../../../groups';
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
diff --git a/src/components/views/groups/GroupUserSettings.js b/src/components/views/groups/GroupUserSettings.js
index 3fa05cad0a..a65d23bed7 100644
--- a/src/components/views/groups/GroupUserSettings.js
+++ b/src/components/views/groups/GroupUserSettings.js
@@ -16,12 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import createReactClass from 'create-react-class';
-<<<<<<< HEAD
 import * as sdk from '../../../index';
-import { MatrixClient } from 'matrix-js-sdk';
-=======
-import sdk from '../../../index';
->>>>>>> develop
 import { _t } from '../../../languageHandler';
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
 
diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js
index 07ee91580e..b5febb689e 100644
--- a/src/components/views/room_settings/AliasSettings.js
+++ b/src/components/views/room_settings/AliasSettings.js
@@ -15,25 +15,15 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-<<<<<<< HEAD
-import React from "react";
-=======
 import EditableItemList from "../elements/EditableItemList";
-
 import React, {createRef} from 'react';
->>>>>>> develop
 import PropTypes from 'prop-types';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import * as sdk from "../../../index";
 import { _t } from '../../../languageHandler';
 import Field from "../elements/Field";
 import ErrorDialog from "../dialogs/ErrorDialog";
-<<<<<<< HEAD
-import Modal from "../../../Modal";
-=======
 import AccessibleButton from "../elements/AccessibleButton";
-const Modal = require("../../../Modal");
->>>>>>> develop
 
 class EditableAliasesList extends EditableItemList {
     constructor(props) {
diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js
index a11821d99c..af3f58f9db 100644
--- a/src/components/views/room_settings/RelatedGroupSettings.js
+++ b/src/components/views/room_settings/RelatedGroupSettings.js
@@ -16,13 +16,8 @@ limitations under the License.
 
 import React from 'react';
 import PropTypes from 'prop-types';
-<<<<<<< HEAD
-import {MatrixEvent, MatrixClient} from 'matrix-js-sdk';
-import * as sdk from '../../../index';
-=======
 import {MatrixEvent} from 'matrix-js-sdk';
-import sdk from '../../../index';
->>>>>>> develop
+import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
 import ErrorDialog from "../dialogs/ErrorDialog";
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index cc00810188..dce4dc8a93 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -23,30 +23,17 @@ import PropTypes from 'prop-types';
 import createReactClass from 'create-react-class';
 import classNames from "classnames";
 import { _t, _td } from '../../../languageHandler';
-<<<<<<< HEAD
 import * as TextForEvent from "../../../TextForEvent";
-import Modal from "../../../Modal";
 import * as sdk from "../../../index";
-=======
-
-const sdk = require('../../../index');
-const TextForEvent = require('../../../TextForEvent');
-
->>>>>>> develop
 import dis from '../../../dispatcher';
 import SettingsStore from "../../../settings/SettingsStore";
 import {EventStatus} from 'matrix-js-sdk';
 import {formatTime} from "../../../DateUtils";
 import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
-<<<<<<< HEAD
 import * as ObjectUtils from "../../../ObjectUtils";
-=======
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
 
-const ObjectUtils = require('../../../ObjectUtils');
->>>>>>> develop
-
 const eventTileTypes = {
     'm.room.message': 'messages.MessageEvent',
     'm.sticker': 'messages.MessageEvent',
diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js
index 3c9118aacb..c6374db464 100644
--- a/src/components/views/rooms/LinkPreviewWidget.js
+++ b/src/components/views/rooms/LinkPreviewWidget.js
@@ -21,14 +21,11 @@ import createReactClass from 'create-react-class';
 import { AllHtmlEntities } from 'html-entities';
 import {linkifyElement} from '../../../HtmlUtils';
 import SettingsStore from "../../../settings/SettingsStore";
-<<<<<<< HEAD
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import * as sdk from "../../../index";
 import Modal from "../../../Modal";
 import * as ImageUtils from "../../../ImageUtils";
-=======
 import { _t } from "../../../languageHandler";
->>>>>>> develop
 
 export default createReactClass({
     displayName: 'LinkPreviewWidget',
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index e179790d39..55855bbc9a 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -46,13 +46,8 @@ import MultiInviter from "../../../utils/MultiInviter";
 import SettingsStore from "../../../settings/SettingsStore";
 import E2EIcon from "./E2EIcon";
 import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
-<<<<<<< HEAD
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-import {EventTimeline} from "matrix-js-sdk";
-=======
-import MatrixClientPeg from "../../../MatrixClientPeg";
 import MatrixClientContext from "../../../contexts/MatrixClientContext";
->>>>>>> develop
 
 export default createReactClass({
     displayName: 'MemberInfo',
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js
index 54fc679b3b..07cb02bd8e 100644
--- a/src/components/views/settings/KeyBackupPanel.js
+++ b/src/components/views/settings/KeyBackupPanel.js
@@ -21,12 +21,7 @@ import * as sdk from '../../../index';
 import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
 import Modal from '../../../Modal';
-<<<<<<< HEAD
-import SettingsStore from '../../../../src/settings/SettingsStore';
-import { accessSecretStorage } from '../../../CrossSigningManager';
-=======
 import SettingsStore from '../../../settings/SettingsStore';
->>>>>>> develop
 
 export default class KeyBackupPanel extends React.PureComponent {
     constructor(props) {
diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
index f56e81f015..b65f8d49a4 100644
--- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
+++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js
@@ -18,12 +18,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
 import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
-<<<<<<< HEAD
-import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import * as sdk from "../../../../..";
-=======
-import sdk from "../../../../..";
->>>>>>> develop
 import AccessibleButton from "../../../elements/AccessibleButton";
 import dis from "../../../../../dispatcher";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
diff --git a/src/components/views/settings/tabs/user/FlairUserSettingsTab.js b/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
index fbcecd1313..26e0033233 100644
--- a/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/FlairUserSettingsTab.js
@@ -17,12 +17,6 @@ limitations under the License.
 import React from 'react';
 import {_t} from "../../../../../languageHandler";
 import GroupUserSettings from "../../../groups/GroupUserSettings";
-<<<<<<< HEAD
-import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
-import PropTypes from "prop-types";
-import {MatrixClient} from "matrix-js-sdk";
-=======
->>>>>>> develop
 
 export default class FlairUserSettingsTab extends React.Component {
     render() {

From 727ce892de8c23e1dd0ad8239b9bd72291069787 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 15:54:51 -0700
Subject: [PATCH 54/86] Fix remaining RoomView conflict

RoomContext was pulled out to its own file.
---
 src/components/structures/RoomView.js | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 3c311d2b83..a24df775e2 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -66,17 +66,7 @@ if (DEBUG) {
     debuglog = console.log.bind(console);
 }
 
-<<<<<<< HEAD
-export const RoomContext = PropTypes.shape({
-    canReact: PropTypes.bool.isRequired,
-    canReply: PropTypes.bool.isRequired,
-    room: PropTypes.instanceOf(Room),
-});
-
 export default createReactClass({
-=======
-module.exports = createReactClass({
->>>>>>> develop
     displayName: 'RoomView',
     propTypes: {
         ConferenceHandler: PropTypes.any,

From 19f78d4d972979268208b43d06cfaa27bae81cb8 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 15:55:02 -0700
Subject: [PATCH 55/86] Fix class construction in MemberList

---
 src/components/views/rooms/MemberList.js | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js
index 86199d7535..edd2f52496 100644
--- a/src/components/views/rooms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -32,15 +32,11 @@ const INITIAL_LOAD_NUM_MEMBERS = 30;
 const INITIAL_LOAD_NUM_INVITED = 5;
 const SHOW_MORE_INCREMENT = 100;
 
-<<<<<<< HEAD
-export default createReactClass({
-=======
 // Regex applied to filter our punctuation in member names before applying sort, to fuzzy it a little
 // matches all ASCII punctuation: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
 const SORT_REGEX = /[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/g;
 
-module.exports = createReactClass({
->>>>>>> develop
+export default createReactClass({
     displayName: 'MemberList',
 
     getInitialState: function() {

From a6376461d03c77aa08bf4203d72e0f8e9fd90ec4 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 15:55:29 -0700
Subject: [PATCH 56/86] Use yarn's updated lockfile

Didn't manually handle this conflict, just let yarn do its thing.
---
 yarn.lock | 94 ++++++-------------------------------------------------
 1 file changed, 10 insertions(+), 84 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 4942802b37..0602190974 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -281,7 +281,6 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb"
   integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==
 
-<<<<<<< HEAD
 "@babel/parser@^7.7.5":
   version "7.7.5"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
@@ -859,14 +858,13 @@
     make-dir "^2.1.0"
     pirates "^4.0.0"
     source-map-support "^0.5.16"
-=======
-"@babel/runtime@^7.0.0":
+
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.7.6":
   version "7.7.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
   integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
   dependencies:
     regenerator-runtime "^0.13.2"
->>>>>>> develop
 
 "@babel/runtime@^7.1.2":
   version "7.7.4"
@@ -875,13 +873,6 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
-"@babel/runtime@^7.7.6":
-  version "7.7.6"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
-  integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
-  dependencies:
-    regenerator-runtime "^0.13.2"
-
 "@babel/template@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
@@ -2075,9 +2066,6 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-<<<<<<< HEAD
-chokidar@^2.0.2, chokidar@^2.1.2, chokidar@^2.1.8:
-=======
 cheerio@^1.0.0-rc.3:
   version "1.0.0-rc.3"
   resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6"
@@ -2090,24 +2078,7 @@ cheerio@^1.0.0-rc.3:
     lodash "^4.15.0"
     parse5 "^3.0.1"
 
-chokidar@^1.6.1:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
-  integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=
-  dependencies:
-    anymatch "^1.3.0"
-    async-each "^1.0.0"
-    glob-parent "^2.0.0"
-    inherits "^2.0.1"
-    is-binary-path "^1.0.0"
-    is-glob "^2.0.0"
-    path-is-absolute "^1.0.0"
-    readdirp "^2.0.0"
-  optionalDependencies:
-    fsevents "^1.0.0"
-
-chokidar@^2.0.2, chokidar@^2.1.2:
->>>>>>> develop
+chokidar@^2.0.2, chokidar@^2.1.2, chokidar@^2.1.8:
   version "2.1.8"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
   integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
@@ -2270,11 +2241,7 @@ commander@2.15.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
   integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
 
-<<<<<<< HEAD
-commander@^2.12.1, commander@^2.20.0:
-=======
-commander@^2.11.0, commander@^2.19.0, commander@^2.20.0:
->>>>>>> develop
+commander@^2.12.1, commander@^2.19.0, commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -4681,21 +4648,11 @@ is-number-object@^1.0.3:
   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799"
   integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=
 
-<<<<<<< HEAD
-=======
 is-number-object@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
   integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
 
-is-number@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
-  integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
-  dependencies:
-    kind-of "^3.0.2"
-
->>>>>>> develop
 is-number@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -6077,8 +6034,6 @@ object.fromentries@^2.0.1:
     function-bind "^1.1.1"
     has "^1.0.3"
 
-<<<<<<< HEAD
-=======
 object.fromentries@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9"
@@ -6089,15 +6044,6 @@ object.fromentries@^2.0.2:
     function-bind "^1.1.1"
     has "^1.0.3"
 
-object.omit@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
-  integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
-  dependencies:
-    for-own "^0.1.4"
-    is-extendable "^0.1.1"
-
->>>>>>> develop
 object.pick@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@@ -6780,8 +6726,6 @@ raf@^3.1.0, raf@^3.4.1:
   dependencies:
     performance-now "^2.1.0"
 
-<<<<<<< HEAD
-=======
 railroad-diagrams@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
@@ -6795,16 +6739,6 @@ randexp@0.4.6:
     discontinuous-range "1.0.0"
     ret "~0.1.10"
 
-randomatic@^3.0.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
-  integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
-  dependencies:
-    is-number "^4.0.0"
-    kind-of "^6.0.0"
-    math-random "^1.0.1"
-
->>>>>>> develop
 randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -7052,7 +6986,11 @@ redux@^3.7.2:
     loose-envify "^1.1.0"
     symbol-observable "^1.0.3"
 
-<<<<<<< HEAD
+reflect.ownkeys@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
+  integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
+
 regenerate-unicode-properties@^8.1.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
@@ -7061,14 +6999,6 @@ regenerate-unicode-properties@^8.1.0:
     regenerate "^1.4.0"
 
 regenerate@^1.4.0:
-=======
-reflect.ownkeys@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
-  integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
-
-regenerate@^1.2.1:
->>>>>>> develop
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
   integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
@@ -8310,11 +8240,7 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-<<<<<<< HEAD
-tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
-=======
-tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
->>>>>>> develop
+tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==

From dc914774fb743f1093368211e18280b246757e00 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Tue, 7 Jan 2020 16:11:00 -0700
Subject: [PATCH 57/86] Delete files that were conflicting in the merge and
 deleted on develop

---
 .../views/rooms/MessageComposerInput.js       | 1516 -----------------
 .../views/rooms/SlateMessageComposer.js       |  485 ------
 src/stores/MessageComposerStore.js            |   67 -
 .../views/rooms/MessageComposerInput-test.js  |  303 ----
 4 files changed, 2371 deletions(-)
 delete mode 100644 src/components/views/rooms/MessageComposerInput.js
 delete mode 100644 src/components/views/rooms/SlateMessageComposer.js
 delete mode 100644 src/stores/MessageComposerStore.js
 delete mode 100644 test/components/views/rooms/MessageComposerInput-test.js

diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
deleted file mode 100644
index 5767309cc0..0000000000
--- a/src/components/views/rooms/MessageComposerInput.js
+++ /dev/null
@@ -1,1516 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-Copyright 2017, 2018 New Vector Ltd
-Copyright 2019 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import { Editor } from 'slate-react';
-import { getEventTransfer } from 'slate-react';
-import { Value, Block, Inline, Range } from 'slate';
-import type { Change } from 'slate';
-
-import Html from 'slate-html-serializer';
-import Md from 'slate-md-serializer';
-import Plain from 'slate-plain-serializer';
-import PlainWithPillsSerializer from "../../../autocomplete/PlainWithPillsSerializer";
-
-import classNames from 'classnames';
-
-import {MatrixClientPeg} from '../../../MatrixClientPeg';
-import type {MatrixClient} from 'matrix-js-sdk/src/matrix';
-import {processCommandInput} from '../../../SlashCommands';
-import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
-import Modal from '../../../Modal';
-import * as sdk from '../../../index';
-import { _t } from '../../../languageHandler';
-import Analytics from '../../../Analytics';
-
-import dis from '../../../dispatcher';
-
-import * as HtmlUtils from '../../../HtmlUtils';
-import Autocomplete from './Autocomplete';
-import {Completion} from "../../../autocomplete/Autocompleter";
-import Markdown from '../../../Markdown';
-import MessageComposerStore from '../../../stores/MessageComposerStore';
-import ContentMessages from '../../../ContentMessages';
-
-import EMOJIBASE from 'emojibase-data/en/compact.json';
-import EMOTICON_REGEX from 'emojibase-regex/emoticon';
-
-import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
-import {getPrimaryPermalinkEntity, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
-import ReplyPreview from "./ReplyPreview";
-import RoomViewStore from '../../../stores/RoomViewStore';
-import ReplyThread from "../elements/ReplyThread";
-import {ContentHelpers} from 'matrix-js-sdk';
-import AccessibleButton from '../elements/AccessibleButton';
-import {findEditableEvent} from '../../../utils/EventUtils';
-import SlateComposerHistoryManager from "../../../SlateComposerHistoryManager";
-import TypingStore from "../../../stores/TypingStore";
-
-const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
-
-// the Slate node type to default to for unstyled text
-const DEFAULT_NODE = 'paragraph';
-
-// map HTML elements through to our Slate schema node types
-// used for the HTML deserializer.
-// (The names here are chosen to match the MD serializer's schema for convenience)
-const BLOCK_TAGS = {
-    p: 'paragraph',
-    blockquote: 'block-quote',
-    ul: 'bulleted-list',
-    h1: 'heading1',
-    h2: 'heading2',
-    h3: 'heading3',
-    h4: 'heading4',
-    h5: 'heading5',
-    h6: 'heading6',
-    li: 'list-item',
-    ol: 'numbered-list',
-    pre: 'code',
-};
-
-const MARK_TAGS = {
-    strong: 'bold',
-    b: 'bold', // deprecated
-    em: 'italic',
-    i: 'italic', // deprecated
-    code: 'code',
-    u: 'underlined',
-    del: 'deleted',
-    strike: 'deleted', // deprecated
-    s: 'deleted', // deprecated
-};
-
-const SLATE_SCHEMA = {
-    inlines: {
-        pill: {
-            isVoid: true,
-        },
-        emoji: {
-            isVoid: true,
-        },
-    },
-};
-
-function onSendMessageFailed(err, room) {
-    // XXX: temporary logging to try to diagnose
-    // https://github.com/vector-im/riot-web/issues/3148
-    console.log('MessageComposer got send failure: ' + err.name + '('+err+')');
-    dis.dispatch({
-        action: 'message_send_failed',
-    });
-}
-
-function rangeEquals(a: Range, b: Range): boolean {
-    return (a.anchor.key === b.anchor.key
-        && a.anchor.offset === b.anchorOffset
-        && a.focus.key === b.focusKey
-        && a.focus.offset === b.focusOffset
-        && a.isFocused === b.isFocused
-        && a.isBackward === b.isBackward);
-}
-
-/*
- * The textInput part of the MessageComposer
- */
-export default class MessageComposerInput extends React.Component {
-    static propTypes = {
-        // js-sdk Room object
-        room: PropTypes.object.isRequired,
-
-        onInputStateChanged: PropTypes.func,
-    };
-
-    client: MatrixClient;
-    autocomplete: Autocomplete;
-    historyManager: SlateComposerHistoryManager;
-
-    constructor(props, context) {
-        super(props, context);
-
-        const isRichTextEnabled = SettingsStore.getValue('MessageComposerInput.isRichTextEnabled');
-
-        Analytics.setRichtextMode(isRichTextEnabled);
-
-        this.client = MatrixClientPeg.get();
-
-        // track whether we should be trying to show autocomplete suggestions on the current editor
-        // contents. currently it's only suppressed when navigating history to avoid ugly flashes
-        // of unexpected corrections as you navigate.
-        // XXX: should this be in state?
-        this.suppressAutoComplete = false;
-
-        // track whether we've just pressed an arrowkey left or right in order to skip void nodes.
-        // see https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095
-        this.direction = '';
-
-        this.plainWithMdPills = new PlainWithPillsSerializer({ pillFormat: 'md' });
-        this.plainWithIdPills = new PlainWithPillsSerializer({ pillFormat: 'id' });
-        this.plainWithPlainPills = new PlainWithPillsSerializer({ pillFormat: 'plain' });
-
-        this.md = new Md({
-            rules: [
-                {
-                    // if serialize returns undefined it falls through to the default hardcoded
-                    // serialization rules
-                    serialize: (obj, children) => {
-                        if (obj.object !== 'inline') return;
-                        switch (obj.type) {
-                            case 'pill':
-                                return `[${ obj.data.get('completion') }](${ obj.data.get('href') })`;
-                            case 'emoji':
-                                return obj.data.get('emojiUnicode');
-                        }
-                    },
-                }, {
-                    serialize: (obj, children) => {
-                        if (obj.object !== 'mark') return;
-                        // XXX: slate-md-serializer consumes marks other than bold, italic, code, inserted, deleted
-                        switch (obj.type) {
-                            case 'underlined':
-                                return `<u>${ children }</u>`;
-                            case 'deleted':
-                                return `<del>${ children }</del>`;
-                            case 'code':
-                                // XXX: we only ever get given `code` regardless of whether it was inline or block
-                                // XXX: workaround for https://github.com/tommoor/slate-md-serializer/issues/14
-                                // strip single backslashes from children, as they would have been escaped here
-                                return `\`${ children.split('\\').map((v) => v ? v : '\\').join('') }\``;
-                        }
-                    },
-                },
-            ],
-        });
-
-        this.html = new Html({
-            rules: [
-                {
-                    deserialize: (el, next) => {
-                        const tag = el.tagName.toLowerCase();
-                        let type = BLOCK_TAGS[tag];
-                        if (type) {
-                            return {
-                                object: 'block',
-                                type: type,
-                                nodes: next(el.childNodes),
-                            };
-                        }
-                        type = MARK_TAGS[tag];
-                        if (type) {
-                            return {
-                                object: 'mark',
-                                type: type,
-                                nodes: next(el.childNodes),
-                            };
-                        }
-                        // special case links
-                        if (tag === 'a') {
-                            const href = el.getAttribute('href');
-                            const permalinkEntity = getPrimaryPermalinkEntity(href);
-                            if (permalinkEntity) {
-                                return {
-                                    object: 'inline',
-                                    type: 'pill',
-                                    data: {
-                                        href,
-                                        completion: el.innerText,
-                                        completionId: permalinkEntity,
-                                    },
-                                };
-                            } else {
-                                return {
-                                    object: 'inline',
-                                    type: 'link',
-                                    data: { href },
-                                    nodes: next(el.childNodes),
-                                };
-                            }
-                        }
-                    },
-                    serialize: (obj, children) => {
-                        if (obj.object === 'block') {
-                            return this.renderNode({
-                                node: obj,
-                                children: children,
-                            });
-                        } else if (obj.object === 'mark') {
-                            return this.renderMark({
-                                mark: obj,
-                                children: children,
-                            });
-                        } else if (obj.object === 'inline') {
-                            // special case links, pills and emoji otherwise we
-                            // end up with React components getting rendered out(!)
-                            switch (obj.type) {
-                                case 'pill':
-                                    return <a href={ obj.data.get('href') }>{ obj.data.get('completion') }</a>;
-                                case 'link':
-                                    return <a href={ obj.data.get('href') }>{ children }</a>;
-                                case 'emoji':
-                                    // XXX: apparently you can't return plain strings from serializer rules
-                                    // until https://github.com/ianstormtaylor/slate/pull/1854 is merged.
-                                    // So instead we temporarily wrap emoji from RTE in a span.
-                                    return <span>{ obj.data.get('emojiUnicode') }</span>;
-                            }
-                            return this.renderNode({
-                                node: obj,
-                                children: children,
-                            });
-                        }
-                    },
-                },
-            ],
-        });
-
-        const savedState = MessageComposerStore.getEditorState(this.props.room.roomId);
-        this.state = {
-            // whether we're in rich text or markdown mode
-            isRichTextEnabled,
-
-            // the currently displayed editor state (note: this is always what is modified on input)
-            editorState: this.createEditorState(
-                isRichTextEnabled,
-                savedState ? savedState.editor_state : undefined,
-                savedState ? savedState.rich_text : undefined,
-            ),
-
-            // the original editor state, before we started tabbing through completions
-            originalEditorState: null,
-
-            // the virtual state "above" the history stack, the message currently being composed that
-            // we want to persist whilst browsing history
-            currentlyComposedEditorState: null,
-
-            // whether there were any completions
-            someCompletions: null,
-        };
-    }
-
-    /*
-     * "Does the right thing" to create an Editor value, based on:
-     * - whether we've got rich text mode enabled
-     * - contentState was passed in
-     * - whether the contentState that was passed in was rich text
-     */
-    createEditorState(wantRichText: boolean, editorState: ?Value, wasRichText: ?boolean): Value {
-        if (editorState instanceof Value) {
-            if (wantRichText && !wasRichText) {
-                return this.mdToRichEditorState(editorState);
-            }
-            if (wasRichText && !wantRichText) {
-                return this.richToMdEditorState(editorState);
-            }
-            return editorState;
-        } else {
-            // ...or create a new one. and explicitly focus it otherwise tab in-out issues
-            const base = Plain.deserialize('', { defaultBlock: DEFAULT_NODE });
-            return base.change().focus().value;
-        }
-    }
-
-    componentWillMount() {
-        this.dispatcherRef = dis.register(this.onAction);
-        this.historyManager = new SlateComposerHistoryManager(this.props.room.roomId, 'mx_slate_composer_history_');
-    }
-
-    componentWillUnmount() {
-        dis.unregister(this.dispatcherRef);
-    }
-
-    _collectEditor = (e) => {
-        this._editor = e;
-    }
-
-    onAction = (payload) => {
-        const editorState = this.state.editorState;
-
-        switch (payload.action) {
-            case 'reply_to_event':
-            case 'focus_composer':
-                this.focusComposer();
-                break;
-            case 'insert_mention':
-                {
-                    // Pretend that we've autocompleted this user because keeping two code
-                    // paths for inserting a user pill is not fun
-                    const selection = this.getSelectionRange(this.state.editorState);
-                    const member = this.props.room.getMember(payload.user_id);
-                    const completion = member ?
-                        member.rawDisplayName : payload.user_id;
-                    this.setDisplayedCompletion({
-                        completion,
-                        completionId: payload.user_id,
-                        selection,
-                        href: makeUserPermalink(payload.user_id),
-                        suffix: (selection.beginning && selection.start === 0) ? ': ' : ' ',
-                    });
-                }
-                break;
-            case 'quote': {
-                const html = HtmlUtils.bodyToHtml(payload.event.getContent(), null, {
-                    forComposerQuote: true,
-                    returnString: true,
-                });
-                const fragment = this.html.deserialize(html);
-                // FIXME: do we want to put in a permalink to the original quote here?
-                // If so, what should be the format, and how do we differentiate it from replies?
-
-                const quote = Block.create('block-quote');
-                if (this.state.isRichTextEnabled) {
-                    let change = editorState.change();
-                    const anchorText = editorState.anchorText;
-                    if ((!anchorText || anchorText.text === '') && editorState.anchorBlock.nodes.size === 1) {
-                        // replace the current block rather than split the block
-                        // XXX: this destroys our focus by deleting the thing we are anchored/focused on
-                        change = change.replaceNodeByKey(editorState.anchorBlock.key, quote);
-                    } else {
-                        // insert it into the middle of the block (splitting it)
-                        change = change.insertBlock(quote);
-                    }
-
-                    // XXX: heuristic to strip out wrapping <p> which breaks quoting in RT mode
-                    if (fragment.document.nodes.size && fragment.document.nodes.get(0).type === DEFAULT_NODE) {
-                        change = change.insertFragmentByKey(quote.key, 0, fragment.document.nodes.get(0));
-                    } else {
-                        change = change.insertFragmentByKey(quote.key, 0, fragment.document);
-                    }
-
-                    // XXX: this is to bring back the focus in a sane place and add a paragraph after it
-                    change = change.select(Range.create({
-                        anchor: {
-                            key: quote.key,
-                        },
-                        focus: {
-                            key: quote.key,
-                        },
-                    })).moveToEndOfBlock().insertBlock(Block.create(DEFAULT_NODE)).focus();
-
-                    this.onChange(change);
-                } else {
-                    const fragmentChange = fragment.change();
-                    fragmentChange.moveToRangeOfNode(fragment.document)
-                                  .wrapBlock(quote);
-
-                    // FIXME: handle pills and use commonmark rather than md-serialize
-                    const md = this.md.serialize(fragmentChange.value);
-                    const change = editorState.change()
-                                            .insertText(md + '\n\n')
-                                            .focus();
-                    this.onChange(change);
-                }
-            }
-                break;
-        }
-    };
-
-    onChange = (change: Change, originalEditorState?: Value) => {
-        let editorState = change.value;
-
-        if (this.direction !== '') {
-            const focusedNode = editorState.focusInline || editorState.focusText;
-            if (editorState.schema.isVoid(focusedNode)) {
-                // XXX: does this work in RTL?
-                const edge = this.direction === 'Previous' ? 'End' : 'Start';
-                if (editorState.selection.isCollapsed) {
-                    change = change[`moveTo${ edge }Of${ this.direction }Text`]();
-                } else {
-                    const block = this.direction === 'Previous' ? editorState.previousText : editorState.nextText;
-                    if (block) {
-                        change = change[`moveFocusTo${ edge }OfNode`](block);
-                    }
-                }
-                editorState = change.value;
-            }
-        }
-
-        // when in autocomplete mode and selection changes hide the autocomplete.
-        // Selection changes when we enter text so use a heuristic to compare documents without doing it recursively
-        if (this.autocomplete.state.completionList.length > 0 && !this.autocomplete.state.hide &&
-            !rangeEquals(this.state.editorState.selection, editorState.selection) &&
-            // XXX: the heuristic failed when inlines like pills weren't taken into account. This is inideal
-            this.state.editorState.document.toJSON() === editorState.document.toJSON()) {
-            this.autocomplete.hide();
-        }
-
-        if (Plain.serialize(editorState) !== '') {
-            TypingStore.sharedInstance().setSelfTyping(this.props.room.roomId, true);
-        } else {
-            TypingStore.sharedInstance().setSelfTyping(this.props.room.roomId, false);
-        }
-
-        if (editorState.startText !== null) {
-            const text = editorState.startText.text;
-            const currentStartOffset = editorState.selection.start.offset;
-
-            // Automatic replacement of plaintext emoji to Unicode emoji
-            if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) {
-                // The first matched group includes just the matched plaintext emoji
-                const emoticonMatch = REGEX_EMOTICON_WHITESPACE.exec(text.slice(0, currentStartOffset));
-                if (emoticonMatch) {
-                    const query = emoticonMatch[1].toLowerCase().replace("-", "");
-                    const data = EMOJIBASE.find(e => e.emoticon ? e.emoticon.toLowerCase() === query : false);
-
-                    // only perform replacement if we found a match, otherwise we would be not letting user type
-                    if (data) {
-                        const range = Range.create({
-                            anchor: {
-                                key: editorState.startText.key,
-                                offset: currentStartOffset - emoticonMatch[1].length - 1,
-                            },
-                            focus: {
-                                key: editorState.startText.key,
-                                offset: currentStartOffset - 1,
-                            },
-                        });
-                        change = change.insertTextAtRange(range, data.unicode);
-                        editorState = change.value;
-                    }
-                }
-            }
-        }
-
-        if (this.props.onInputStateChanged && editorState.blocks.size > 0) {
-            let blockType = editorState.blocks.first().type;
-            // console.log("onInputStateChanged; current block type is " + blockType + " and marks are " + editorState.activeMarks);
-
-            if (blockType === 'list-item') {
-                const parent = editorState.document.getParent(editorState.blocks.first().key);
-                if (parent.type === 'numbered-list') {
-                    blockType = 'numbered-list';
-                } else if (parent.type === 'bulleted-list') {
-                    blockType = 'bulleted-list';
-                }
-            }
-            const inputState = {
-                marks: editorState.activeMarks,
-                blockType,
-            };
-            this.props.onInputStateChanged(inputState);
-        }
-
-        // Record the editor state for this room so that it can be retrieved after switching to another room and back
-        MessageComposerStore.setEditorState(this.props.room.roomId, editorState, this.state.isRichTextEnabled);
-
-        this.setState({
-            editorState,
-            originalEditorState: originalEditorState || null,
-        });
-    };
-
-    mdToRichEditorState(editorState: Value): Value {
-        // for consistency when roundtripping, we could use slate-md-serializer rather than
-        // commonmark, but then we would lose pills as the MD deserialiser doesn't know about
-        // them and doesn't have any extensibility hooks.
-        //
-        // The code looks like this:
-        //
-        // const markdown = this.plainWithMdPills.serialize(editorState);
-        //
-        // // weirdly, the Md serializer can't deserialize '' to a valid Value...
-        // if (markdown !== '') {
-        //     editorState = this.md.deserialize(markdown);
-        // }
-        // else {
-        //     editorState = Plain.deserialize('', { defaultBlock: DEFAULT_NODE });
-        // }
-
-        // so, instead, we use commonmark proper (which is arguably more logical to the user
-        // anyway, as they'll expect the RTE view to match what they'll see in the timeline,
-        // but the HTML->MD conversion is anyone's guess).
-
-        const textWithMdPills = this.plainWithMdPills.serialize(editorState);
-        const markdown = new Markdown(textWithMdPills);
-        // HTML deserialize has custom rules to turn permalinks into pill objects.
-        return this.html.deserialize(markdown.toHTML());
-    }
-
-    richToMdEditorState(editorState: Value): Value {
-        // FIXME: this conversion loses pills (turning them into pure MD links).
-        // We need to add a pill-aware deserialize method
-        // to PlainWithPillsSerializer which recognises pills in raw MD and turns them into pills.
-        return Plain.deserialize(
-            // FIXME: we compile the MD out of the RTE state using slate-md-serializer
-            // which doesn't roundtrip symmetrically with commonmark, which we use for
-            // compiling MD out of the MD editor state above.
-            this.md.serialize(editorState),
-            { defaultBlock: DEFAULT_NODE },
-        );
-    }
-
-    enableRichtext(enabled: boolean) {
-        if (enabled === this.state.isRichTextEnabled) return;
-
-        Analytics.setRichtextMode(enabled);
-
-        this.setState({
-            editorState: this.createEditorState(
-                enabled,
-                this.state.editorState,
-                this.state.isRichTextEnabled,
-            ),
-            isRichTextEnabled: enabled,
-        }, () => {
-            this._editor.focus();
-            if (this.props.onInputStateChanged) {
-                this.props.onInputStateChanged({
-                    isRichTextEnabled: enabled,
-                });
-            }
-        });
-
-        SettingsStore.setValue("MessageComposerInput.isRichTextEnabled", null, SettingLevel.ACCOUNT, enabled);
-    }
-
-    /**
-    * Check if the current selection has a mark with `type` in it.
-    *
-    * @param {String} type
-    * @return {Boolean}
-    */
-
-    hasMark = type => {
-        const { editorState } = this.state;
-        return editorState.activeMarks.some(mark => mark.type === type);
-    };
-
-    /**
-    * Check if the any of the currently selected blocks are of `type`.
-    *
-    * @param {String} type
-    * @return {Boolean}
-    */
-
-    hasBlock = type => {
-        const { editorState } = this.state;
-        return editorState.blocks.some(node => node.type === type);
-    };
-
-    onKeyDown = (ev: KeyboardEvent, change: Change, editor: Editor) => {
-        this.suppressAutoComplete = false;
-        this.direction = '';
-
-        // Navigate autocomplete list with arrow keys
-        if (this.autocomplete.countCompletions() > 0) {
-            if (!(ev.ctrlKey || ev.shiftKey || ev.altKey || ev.metaKey)) {
-                switch (ev.keyCode) {
-                    case KeyCode.UP:
-                        this.autocomplete.moveSelection(-1);
-                        ev.preventDefault();
-                        return true;
-                    case KeyCode.DOWN:
-                        this.autocomplete.moveSelection(+1);
-                        ev.preventDefault();
-                        return true;
-                }
-            }
-        }
-
-        // skip void nodes - see
-        // https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095
-        if (ev.keyCode === KeyCode.LEFT) {
-            this.direction = 'Previous';
-        } else if (ev.keyCode === KeyCode.RIGHT) {
-            this.direction = 'Next';
-        }
-
-        switch (ev.keyCode) {
-            case KeyCode.ENTER:
-                return this.handleReturn(ev, change);
-            case KeyCode.BACKSPACE:
-                return this.onBackspace(ev, change);
-            case KeyCode.UP:
-                return this.onVerticalArrow(ev, true);
-            case KeyCode.DOWN:
-                return this.onVerticalArrow(ev, false);
-            case KeyCode.TAB:
-                return this.onTab(ev);
-            case KeyCode.ESCAPE:
-                return this.onEscape(ev);
-            case KeyCode.SPACE:
-                return this.onSpace(ev, change);
-        }
-
-        if (isOnlyCtrlOrCmdKeyEvent(ev)) {
-            const ctrlCmdCommand = {
-                // C-m => Toggles between rich text and markdown modes
-                [KeyCode.KEY_M]: 'toggle-mode',
-                [KeyCode.KEY_B]: 'bold',
-                [KeyCode.KEY_I]: 'italic',
-                [KeyCode.KEY_U]: 'underlined',
-                [KeyCode.KEY_J]: 'inline-code',
-            }[ev.keyCode];
-
-            if (ctrlCmdCommand) {
-                ev.preventDefault(); // to prevent clashing with Mac's minimize window
-                return this.handleKeyCommand(ctrlCmdCommand);
-            }
-        }
-    };
-
-    onSpace = (ev: KeyboardEvent, change: Change): Change => {
-        if (ev.metaKey || ev.altKey || ev.shiftKey || ev.ctrlKey) {
-            return;
-        }
-
-        // drop a point in history so the user can undo a word
-        // XXX: this seems nasty but adding to history manually seems a no-go
-        ev.preventDefault();
-        return change.withoutMerging(() => {
-            change.insertText(ev.key);
-        });
-    };
-
-    onBackspace = (ev: KeyboardEvent, change: Change): Change => {
-        if (ev.metaKey || ev.altKey || ev.shiftKey) {
-            return;
-        }
-
-        const { editorState } = this.state;
-
-        // Allow Ctrl/Cmd-Backspace when focus starts at the start of the composer (e.g select-all)
-        // for some reason if slate sees you Ctrl-backspace and your anchor.offset=0 it just resets your focus
-        // XXX: Doing this now seems to put slate into a broken state, and it didn't appear to be doing
-        // what it claims to do on the old version of slate anyway...
-        /*if (!editorState.isCollapsed && editorState.selection.anchor.offset === 0) {
-            return change.delete();
-        }*/
-
-        if (this.state.isRichTextEnabled) {
-            // let backspace exit lists
-            const isList = this.hasBlock('list-item');
-
-            if (isList && editorState.selection.anchor.offset == 0) {
-                change
-                    .setBlocks(DEFAULT_NODE)
-                    .unwrapBlock('bulleted-list')
-                    .unwrapBlock('numbered-list');
-                return change;
-            } else if (editorState.selection.anchor.offset == 0 && editorState.isCollapsed) {
-                // turn blocks back into paragraphs
-                if ((this.hasBlock('block-quote') ||
-                     this.hasBlock('heading1') ||
-                     this.hasBlock('heading2') ||
-                     this.hasBlock('heading3') ||
-                     this.hasBlock('heading4') ||
-                     this.hasBlock('heading5') ||
-                     this.hasBlock('heading6') ||
-                     this.hasBlock('code'))) {
-                    return change.setBlocks(DEFAULT_NODE);
-                }
-
-                // remove paragraphs entirely if they're nested
-                const parent = editorState.document.getParent(editorState.anchorBlock.key);
-                if (editorState.selection.anchor.offset == 0 &&
-                    this.hasBlock('paragraph') &&
-                    parent.nodes.size == 1 &&
-                    parent.object !== 'document') {
-                    return change.replaceNodeByKey(editorState.anchorBlock.key, editorState.anchorText)
-                                 .moveToEndOfNode(parent)
-                                 .focus();
-                }
-            }
-        }
-        return;
-    };
-
-    handleKeyCommand = (command: string): boolean => {
-        if (command === 'toggle-mode') {
-            this.enableRichtext(!this.state.isRichTextEnabled);
-            return true;
-        }
-
-        //const newState: ?Value = null;
-
-        // Draft handles rich text mode commands by default but we need to do it ourselves for Markdown.
-        if (this.state.isRichTextEnabled) {
-            const type = command;
-            const { editorState } = this.state;
-            const change = editorState.change();
-            const { document } = editorState;
-            switch (type) {
-                // list-blocks:
-                case 'bulleted-list':
-                case 'numbered-list': {
-                    // Handle the extra wrapping required for list buttons.
-                    const isList = this.hasBlock('list-item');
-                    const isType = editorState.blocks.some(block => {
-                        return !!document.getClosest(block.key, parent => parent.type === type);
-                    });
-
-                    if (isList && isType) {
-                        change
-                            .setBlocks(DEFAULT_NODE)
-                            .unwrapBlock('bulleted-list')
-                            .unwrapBlock('numbered-list');
-                    } else if (isList) {
-                        change
-                            .unwrapBlock(
-                                type === 'bulleted-list' ? 'numbered-list' : 'bulleted-list',
-                            )
-                            .wrapBlock(type);
-                    } else {
-                        change.setBlocks('list-item').wrapBlock(type);
-                    }
-                }
-                break;
-
-                // simple blocks
-                case 'paragraph':
-                case 'block-quote':
-                case 'heading1':
-                case 'heading2':
-                case 'heading3':
-                case 'heading4':
-                case 'heading5':
-                case 'heading6':
-                case 'list-item':
-                case 'code': {
-                    const isActive = this.hasBlock(type);
-                    const isList = this.hasBlock('list-item');
-
-                    if (isList) {
-                        change
-                            .setBlocks(isActive ? DEFAULT_NODE : type)
-                            .unwrapBlock('bulleted-list')
-                            .unwrapBlock('numbered-list');
-                    } else {
-                        change.setBlocks(isActive ? DEFAULT_NODE : type);
-                    }
-                }
-                break;
-
-                // marks:
-                case 'bold':
-                case 'italic':
-                case 'inline-code':
-                case 'underlined':
-                case 'deleted': {
-                    change.toggleMark(type === 'inline-code' ? 'code' : type);
-                }
-                break;
-
-                default:
-                    console.warn(`ignoring unrecognised RTE command ${type}`);
-                    return false;
-            }
-
-            this.onChange(change);
-
-            return true;
-        } else {
-/*
-            const contentState = this.state.editorState.getCurrentContent();
-            const multipleLinesSelected = RichText.hasMultiLineSelection(this.state.editorState);
-
-            const selectionState = this.state.editorState.getSelection();
-            const start = selectionState.getStartOffset();
-            const end = selectionState.getEndOffset();
-
-            // If multiple lines are selected or nothing is selected, insert a code block
-            // instead of applying inline code formatting. This is an attempt to mimic what
-            // happens in non-MD mode.
-            const treatInlineCodeAsBlock = multipleLinesSelected || start === end;
-            const textMdCodeBlock = (text) => `\`\`\`\n${text}\n\`\`\`\n`;
-            const modifyFn = {
-                'bold': (text) => `**${text}**`,
-                'italic': (text) => `*${text}*`,
-                'underline': (text) => `<u>${text}</u>`,
-                'strike': (text) => `<del>${text}</del>`,
-                // ("code" is triggered by ctrl+j by draft-js by default)
-                'code': (text) => treatInlineCodeAsBlock ? textMdCodeBlock(text) : `\`${text}\``,
-                'code': textMdCodeBlock,
-                'blockquote': (text) => text.split('\n').map((line) => `> ${line}\n`).join('') + '\n',
-                'unordered-list-item': (text) => text.split('\n').map((line) => `\n- ${line}`).join(''),
-                'ordered-list-item': (text) => text.split('\n').map((line, i) => `\n${i + 1}. ${line}`).join(''),
-            }[command];
-
-            const selectionAfterOffset = {
-                'bold': -2,
-                'italic': -1,
-                'underline': -4,
-                'strike': -6,
-                'code': treatInlineCodeAsBlock ? -5 : -1,
-                'code': -5,
-                'blockquote': -2,
-            }[command];
-
-            // Returns a function that collapses a selection to its end and moves it by offset
-            const collapseAndOffsetSelection = (selection, offset) => {
-                const key = selection.endKey();
-                return new Range({
-                    anchorKey: key, anchor.offset: offset,
-                    focus.key: key, focus.offset: offset,
-                });
-            };
-
-            if (modifyFn) {
-
-                const previousSelection = this.state.editorState.getSelection();
-                const newContentState = RichText.modifyText(contentState, previousSelection, modifyFn);
-                newState = EditorState.push(
-                    this.state.editorState,
-                    newContentState,
-                    'insert-characters',
-                );
-
-                let newSelection = newContentState.getSelectionAfter();
-                // If the selection range is 0, move the cursor inside the formatted body
-                if (previousSelection.getStartOffset() === previousSelection.getEndOffset() &&
-                    previousSelection.getStartKey() === previousSelection.getEndKey() &&
-                    selectionAfterOffset !== undefined
-                ) {
-                    const selectedBlock = newContentState.getBlockForKey(previousSelection.getAnchorKey());
-                    const blockLength = selectedBlock.getText().length;
-                    const newOffset = blockLength + selectionAfterOffset;
-                    newSelection = collapseAndOffsetSelection(newSelection, newOffset);
-                }
-
-                newState = EditorState.forceSelection(newState, newSelection);
-            }
-        }
-
-        if (newState != null) {
-            this.setState({editorState: newState});
-            return true;
-        }
-*/
-        }
-        return false;
-    };
-
-    onPaste = (event: Event, change: Change, editor: Editor): Change => {
-        const transfer = getEventTransfer(event);
-
-        switch (transfer.type) {
-            case 'files':
-                // This actually not so much for 'files' as such (at time of writing
-                // neither chrome nor firefox let you paste a plain file copied
-                // from Finder) but more images copied from a different website
-                // / word processor etc.
-                return ContentMessages.sharedInstance().sendContentListToRoom(
-                    transfer.files, this.props.room.roomId, this.client,
-                );
-            case 'html': {
-                if (this.state.isRichTextEnabled) {
-                    // FIXME: https://github.com/ianstormtaylor/slate/issues/1497 means
-                    // that we will silently discard nested blocks (e.g. nested lists) :(
-                    const fragment = this.html.deserialize(transfer.html);
-                    return change
-                    // XXX: this somehow makes Slate barf on undo and get too empty and break entirely
-                    // .setOperationFlag("skip", false)
-                    // .setOperationFlag("merge", false)
-                        .insertFragment(fragment.document);
-                } else {
-                    // in MD mode we don't want the rich content pasted as the magic was annoying people so paste plain
-                    return change.withoutMerging(() => {
-                        change.insertText(transfer.text);
-                    });
-                }
-            }
-            case 'text':
-                // don't skip/merge so that multiple consecutive pastes can be undone individually
-                return change.withoutMerging(() => {
-                    change.insertText(transfer.text);
-                });
-        }
-    };
-
-    handleReturn = (ev, change) => {
-        const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
-        if (ev.shiftKey || (isMac && ev.altKey)) {
-            return change.insertText('\n');
-        }
-
-        if (this.autocomplete.hasSelection()) {
-            this.autocomplete.hide();
-            ev.preventDefault();
-            return true;
-        }
-
-        const editorState = this.state.editorState;
-
-        const lastBlock = editorState.blocks.last();
-        if (['code', 'block-quote', 'list-item'].includes(lastBlock.type)) {
-            const text = lastBlock.text;
-            if (text === '') {
-                // allow the user to cancel empty block by hitting return, useful in conjunction with below `inBlock`
-                return change
-                    .setBlocks(DEFAULT_NODE)
-                    .unwrapBlock('bulleted-list')
-                    .unwrapBlock('numbered-list');
-            }
-
-            // TODO strip trailing lines from blockquotes/list entries
-            // the below code seemingly works but doesn't account for edge cases like return with caret not at end
-            /* const trailingNewlines = text.match(/\n*$/);
-            if (trailingNewlines && trailingNewlines[0]) {
-                remove trailing newlines at the end of this block before making a new one
-                return change.deleteBackward(trailingNewlines[0].length);
-            }*/
-
-            return;
-        }
-
-        let contentText;
-        let contentHTML;
-
-        // only look for commands if the first block contains simple unformatted text
-        // i.e. no pills or rich-text formatting and begins with a /.
-        let cmd; let commandText;
-        const firstChild = editorState.document.nodes.get(0);
-        const firstGrandChild = firstChild && firstChild.nodes.get(0);
-        if (firstChild && firstGrandChild &&
-            firstChild.object === 'block' && firstGrandChild.object === 'text' &&
-            firstGrandChild.text[0] === '/') {
-            commandText = this.plainWithIdPills.serialize(editorState);
-            cmd = processCommandInput(this.props.room.roomId, commandText);
-        }
-
-        if (cmd) {
-            if (!cmd.error) {
-                this.historyManager.save(editorState, this.state.isRichTextEnabled ? 'rich' : 'markdown');
-                this.setState({
-                    editorState: this.createEditorState(),
-                }, ()=>{
-                    this._editor.focus();
-                });
-            }
-            if (cmd.promise) {
-                cmd.promise.then(()=>{
-                    console.log("Command success.");
-                }, (err)=>{
-                    console.error("Command failure: %s", err);
-                    const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
-                    Modal.createTrackedDialog('Server error', '', ErrorDialog, {
-                        title: _t("Server error"),
-                        description: ((err && err.message) ? err.message : _t(
-                            "Server unavailable, overloaded, or something else went wrong.",
-                        )),
-                    });
-                });
-            } else if (cmd.error) {
-                console.error(cmd.error);
-                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
-                // TODO possibly track which command they ran (not its Arguments) here
-                Modal.createTrackedDialog('Command error', '', ErrorDialog, {
-                    title: _t("Command error"),
-                    description: cmd.error,
-                });
-            }
-            return true;
-        }
-
-        const replyingToEv = RoomViewStore.getQuotingEvent();
-        const mustSendHTML = Boolean(replyingToEv);
-
-        if (this.state.isRichTextEnabled) {
-            // We should only send HTML if any block is styled or contains inline style
-            let shouldSendHTML = false;
-
-            if (mustSendHTML) shouldSendHTML = true;
-
-            if (!shouldSendHTML) {
-                shouldSendHTML = !!editorState.document.findDescendant(node => {
-                    // N.B. node.getMarks() might be private?
-                    return ((node.object === 'block' && node.type !== 'paragraph') ||
-                            (node.object === 'inline') ||
-                            (node.object === 'text' && node.getMarks().size > 0));
-                });
-            }
-
-            contentText = this.plainWithPlainPills.serialize(editorState);
-            if (contentText === '') return true;
-
-            if (shouldSendHTML) {
-                contentHTML = HtmlUtils.processHtmlForSending(this.html.serialize(editorState));
-            }
-        } else {
-            const sourceWithPills = this.plainWithMdPills.serialize(editorState);
-            if (sourceWithPills === '') return true;
-
-            const mdWithPills = new Markdown(sourceWithPills);
-
-            // if contains no HTML and we're not quoting (needing HTML)
-            if (mdWithPills.isPlainText() && !mustSendHTML) {
-                // N.B. toPlainText is only usable here because we know that the MD
-                // didn't contain any formatting in the first place...
-                contentText = mdWithPills.toPlaintext();
-            } else {
-                // to avoid ugliness on clients which ignore the HTML body we don't
-                // send pills in the plaintext body.
-                contentText = this.plainWithPlainPills.serialize(editorState);
-                contentHTML = mdWithPills.toHTML();
-            }
-        }
-
-        let sendHtmlFn = ContentHelpers.makeHtmlMessage;
-        let sendTextFn = ContentHelpers.makeTextMessage;
-
-        this.historyManager.save(editorState, this.state.isRichTextEnabled ? 'rich' : 'markdown');
-
-        if (commandText && commandText.startsWith('/me')) {
-            if (replyingToEv) {
-                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
-                Modal.createTrackedDialog('Emote Reply Fail', '', ErrorDialog, {
-                    title: _t("Unable to reply"),
-                    description: _t("At this time it is not possible to reply with an emote."),
-                });
-                return false;
-            }
-
-            contentText = contentText.substring(4);
-            // bit of a hack, but the alternative would be quite complicated
-            if (contentHTML) contentHTML = contentHTML.replace(/\/me ?/, '');
-            sendHtmlFn = ContentHelpers.makeHtmlEmote;
-            sendTextFn = ContentHelpers.makeEmoteMessage;
-        }
-
-        let content = contentHTML ?
-                      sendHtmlFn(contentText, contentHTML) :
-                      sendTextFn(contentText);
-
-        if (replyingToEv) {
-            const replyContent = ReplyThread.makeReplyMixIn(replyingToEv);
-            content = Object.assign(replyContent, content);
-
-            // Part of Replies fallback support - prepend the text we're sending
-            // with the text we're replying to
-            const nestedReply = ReplyThread.getNestedReplyText(replyingToEv, this.props.permalinkCreator);
-            if (nestedReply) {
-                if (content.formatted_body) {
-                    content.formatted_body = nestedReply.html + content.formatted_body;
-                }
-                content.body = nestedReply.body + content.body;
-            }
-
-            // Clear reply_to_event as we put the message into the queue
-            // if the send fails, retry will handle resending.
-            dis.dispatch({
-                action: 'reply_to_event',
-                event: null,
-            });
-        }
-
-        this.client.sendMessage(this.props.room.roomId, content).then((res) => {
-            dis.dispatch({
-                action: 'message_sent',
-            });
-        }).catch((e) => {
-            onSendMessageFailed(e, this.props.room);
-        });
-
-        this.setState({
-            editorState: this.createEditorState(),
-        }, ()=>{ this._editor.focus(); });
-
-        return true;
-    };
-
-    onVerticalArrow = (e, up) => {
-        if (e.ctrlKey || e.shiftKey || e.metaKey) return;
-
-        const shouldSelectHistory = e.altKey;
-        const shouldEditLastMessage = !e.altKey && up && !RoomViewStore.getQuotingEvent();
-
-        if (shouldSelectHistory) {
-            // Try select composer history
-            const selected = this.selectHistory(up);
-            if (selected) {
-                // We're selecting history, so prevent the key event from doing anything else
-                e.preventDefault();
-            }
-        } else if (shouldEditLastMessage) {
-            // selection must be collapsed
-            const selection = this.state.editorState.selection;
-            if (!selection.isCollapsed) return;
-            // and we must be at the edge of the document (up=start, down=end)
-            const document = this.state.editorState.document;
-            if (up) {
-                if (!selection.anchor.isAtStartOfNode(document)) return;
-            } else {
-                if (!selection.anchor.isAtEndOfNode(document)) return;
-            }
-
-            const editEvent = findEditableEvent(this.props.room, false);
-            if (editEvent) {
-                // We're selecting history, so prevent the key event from doing anything else
-                e.preventDefault();
-                dis.dispatch({
-                    action: 'edit_event',
-                    event: editEvent,
-                });
-            }
-        }
-    };
-
-    selectHistory = (up) => {
-        const delta = up ? -1 : 1;
-
-        // True if we are not currently selecting history, but composing a message
-        if (this.historyManager.currentIndex === this.historyManager.history.length) {
-            // We can't go any further - there isn't any more history, so nop.
-            if (!up) {
-                return;
-            }
-            this.setState({
-                currentlyComposedEditorState: this.state.editorState,
-            });
-        } else if (this.historyManager.currentIndex + delta === this.historyManager.history.length) {
-            // True when we return to the message being composed currently
-            this.setState({
-                editorState: this.state.currentlyComposedEditorState,
-            });
-            this.historyManager.currentIndex = this.historyManager.history.length;
-            return;
-        }
-
-        let editorState;
-        const historyItem = this.historyManager.getItem(delta);
-        if (!historyItem) return;
-
-        if (historyItem.format === 'rich' && !this.state.isRichTextEnabled) {
-            editorState = this.richToMdEditorState(historyItem.value);
-        } else if (historyItem.format === 'markdown' && this.state.isRichTextEnabled) {
-            editorState = this.mdToRichEditorState(historyItem.value);
-        } else {
-            editorState = historyItem.value;
-        }
-
-        // Move selection to the end of the selected history
-        const change = editorState.change().moveToEndOfNode(editorState.document);
-
-        // We don't call this.onChange(change) now, as fixups on stuff like pills
-        // should already have been done and persisted in the history.
-        editorState = change.value;
-
-        this.suppressAutoComplete = true;
-
-        this.setState({ editorState }, ()=>{
-            this._editor.focus();
-        });
-        return true;
-    };
-
-    onTab = async (e) => {
-        this.setState({
-            someCompletions: null,
-        });
-        e.preventDefault();
-        if (this.autocomplete.countCompletions() === 0) {
-            // Force completions to show for the text currently entered
-            const completionCount = await this.autocomplete.forceComplete();
-            this.setState({
-                someCompletions: completionCount > 0,
-            });
-            // Select the first item by moving "down"
-            await this.autocomplete.moveSelection(+1);
-        } else {
-            await this.autocomplete.moveSelection(e.shiftKey ? -1 : +1);
-        }
-    };
-
-    onEscape = async (e) => {
-        e.preventDefault();
-        if (this.autocomplete) {
-            this.autocomplete.onEscape(e);
-        }
-        await this.setDisplayedCompletion(null); // restore originalEditorState
-    };
-
-    onAutocompleteConfirm = (displayedCompletion: ?Completion) => {
-        this.focusComposer();
-        // XXX: this fails if the composer isn't focused so focus it and delay the completion until next tick
-        setImmediate(() => {
-            this.setDisplayedCompletion(displayedCompletion);
-        });
-    };
-
-    /* If passed null, restores the original editor content from state.originalEditorState.
-     * If passed a non-null displayedCompletion, modifies state.originalEditorState to compute new state.editorState.
-     */
-    setDisplayedCompletion = async (displayedCompletion: ?Completion): boolean => {
-        const activeEditorState = this.state.originalEditorState || this.state.editorState;
-
-        if (displayedCompletion == null) {
-            if (this.state.originalEditorState) {
-                const editorState = this.state.originalEditorState;
-                this.setState({editorState});
-            }
-            return false;
-        }
-
-        const {
-            range = null,
-            completion = '',
-            completionId = '',
-            href = null,
-            suffix = '',
-        } = displayedCompletion;
-
-        let inline;
-        if (href) {
-            inline = Inline.create({
-                type: 'pill',
-                data: { completion, completionId, href },
-            });
-        } else if (completion === '@room') {
-            inline = Inline.create({
-                type: 'pill',
-                data: { completion, completionId },
-            });
-        }
-
-        let editorState = activeEditorState;
-
-        if (range) {
-            const change = editorState.change()
-                                      .moveToAnchor()
-                                      .moveAnchorTo(range.start)
-                                      .moveFocusTo(range.end)
-                                      .focus();
-            editorState = change.value;
-        }
-
-        let change;
-        if (inline) {
-            change = editorState.change()
-                                .insertInlineAtRange(editorState.selection, inline)
-                                .insertText(suffix)
-                                .focus();
-        } else {
-            change = editorState.change()
-                                .insertTextAtRange(editorState.selection, completion)
-                                .insertText(suffix)
-                                .focus();
-        }
-        // for good hygiene, keep editorState updated to track the result of the change
-        // even though we don't do anything subsequently with it
-        editorState = change.value;
-
-        this.onChange(change, activeEditorState);
-
-        return true;
-    };
-
-    renderNode = props => {
-        const { attributes, children, node, isSelected } = props;
-
-        switch (node.type) {
-            case 'paragraph':
-                return <p {...attributes}>{children}</p>;
-            case 'block-quote':
-                return <blockquote {...attributes}>{children}</blockquote>;
-            case 'bulleted-list':
-                return <ul {...attributes}>{children}</ul>;
-            case 'heading1':
-                return <h1 {...attributes}>{children}</h1>;
-            case 'heading2':
-                return <h2 {...attributes}>{children}</h2>;
-            case 'heading3':
-                return <h3 {...attributes}>{children}</h3>;
-            case 'heading4':
-                return <h4 {...attributes}>{children}</h4>;
-            case 'heading5':
-                return <h5 {...attributes}>{children}</h5>;
-            case 'heading6':
-                return <h6 {...attributes}>{children}</h6>;
-            case 'list-item':
-                return <li {...attributes}>{children}</li>;
-            case 'numbered-list':
-                return <ol {...attributes}>{children}</ol>;
-            case 'code':
-                return <pre {...attributes}>{children}</pre>;
-            case 'link':
-                return <a {...attributes} href={ node.data.get('href') }>{children}</a>;
-            case 'pill': {
-                const { data } = node;
-                const url = data.get('href');
-                const completion = data.get('completion');
-
-                const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
-                const Pill = sdk.getComponent('elements.Pill');
-
-                if (completion === '@room') {
-                    return <Pill
-                            type={Pill.TYPE_AT_ROOM_MENTION}
-                            room={this.props.room}
-                            shouldShowPillAvatar={shouldShowPillAvatar}
-                            isSelected={isSelected}
-                            {...attributes}
-                            />;
-                } else if (Pill.isPillUrl(url)) {
-                    return <Pill
-                            url={url}
-                            room={this.props.room}
-                            shouldShowPillAvatar={shouldShowPillAvatar}
-                            isSelected={isSelected}
-                            {...attributes}
-                            />;
-                } else {
-                    const { text } = node;
-                    return <a href={url} {...props.attributes}>
-                                { text }
-                           </a>;
-                }
-            }
-            case 'emoji': {
-                const { data } = node;
-                return data.get('emojiUnicode');
-            }
-        }
-    };
-
-    renderMark = props => {
-        const { children, mark, attributes } = props;
-        switch (mark.type) {
-            case 'bold':
-                return <strong {...attributes}>{children}</strong>;
-            case 'italic':
-                return <em {...attributes}>{children}</em>;
-            case 'code':
-                return <code {...attributes}>{children}</code>;
-            case 'underlined':
-                return <u {...attributes}>{children}</u>;
-            case 'deleted':
-                return <del {...attributes}>{children}</del>;
-        }
-    };
-
-    onFormatButtonClicked = (name, e) => {
-        e.preventDefault();
-
-        // XXX: horrible evil hack to ensure the editor is focused so the act
-        // of focusing it doesn't then cancel the format button being pressed
-        // FIXME: can we just tell handleKeyCommand's change to invoke .focus()?
-        if (document.activeElement && document.activeElement.className !== 'mx_MessageComposer_editor') {
-            this._editor.focus();
-            setTimeout(()=>{
-                this.handleKeyCommand(name);
-            }, 500); // can't find any callback to hook this to. onFocus and onChange and willComponentUpdate fire too early.
-            return;
-        }
-
-        this.handleKeyCommand(name);
-    };
-
-    getAutocompleteQuery(editorState: Value) {
-        // We can just return the current block where the selection begins, which
-        // should be enough to capture any autocompletion input, given autocompletion
-        // providers only search for the first match which intersects with the current selection.
-        // This avoids us having to serialize the whole thing to plaintext and convert
-        // selection offsets in & out of the plaintext domain.
-
-        if (editorState.selection.anchor.key) {
-            return editorState.document.getDescendant(editorState.selection.anchor.key).text;
-        } else {
-            return '';
-        }
-    }
-
-    getSelectionRange(editorState: Value) {
-        let beginning = false;
-        const firstChild = editorState.document.nodes.get(0);
-        const firstGrandChild = firstChild && firstChild.nodes.get(0);
-        beginning = (firstChild && firstGrandChild &&
-                     firstChild.object === 'block' && firstGrandChild.object === 'text' &&
-                     editorState.selection.anchor.key === firstGrandChild.key);
-
-        // return a character range suitable for handing to an autocomplete provider.
-        // the range is relative to the anchor of the current editor selection.
-        // if the selection spans multiple blocks, then we collapse it for the calculation.
-        const range = {
-            beginning, // whether the selection is in the first block of the editor or not
-            start: editorState.selection.anchor.offset,
-            end: (editorState.selection.anchor.key == editorState.selection.focus.key) ?
-                 editorState.selection.focus.offset : editorState.selection.anchor.offset,
-        };
-        if (range.start > range.end) {
-            const tmp = range.start;
-            range.start = range.end;
-            range.end = tmp;
-        }
-        return range;
-    }
-
-    onMarkdownToggleClicked = (e) => {
-        e.preventDefault(); // don't steal focus from the editor!
-        this.handleKeyCommand('toggle-mode');
-    };
-
-    focusComposer = () => {
-        this._editor.focus();
-    };
-
-    render() {
-        const activeEditorState = this.state.originalEditorState || this.state.editorState;
-
-        const className = classNames('mx_MessageComposer_input', {
-            mx_MessageComposer_input_error: this.state.someCompletions === false,
-        });
-
-        const isEmpty = Plain.serialize(this.state.editorState) === '';
-
-        let {placeholder} = this.props;
-        // XXX: workaround for placeholder being shown when there is a formatting block e.g blockquote but no text
-        if (isEmpty && this.state.editorState.startBlock && this.state.editorState.startBlock.type !== DEFAULT_NODE) {
-            placeholder = undefined;
-        }
-
-        const markdownClasses = classNames({
-            mx_MessageComposer_input_markdownIndicator: true,
-            mx_MessageComposer_markdownDisabled: this.state.isRichTextEnabled,
-        });
-
-        return (
-            <div className="mx_MessageComposer_input_wrapper" onClick={this.focusComposer}>
-                <div className="mx_MessageComposer_autocomplete_wrapper">
-                    <ReplyPreview permalinkCreator={this.props.permalinkCreator} />
-                    <Autocomplete
-                        ref={(e) => this.autocomplete = e}
-                        room={this.props.room}
-                        onConfirm={this.onAutocompleteConfirm}
-                        onSelectionChange={this.setDisplayedCompletion}
-                        query={ this.suppressAutoComplete ? '' : this.getAutocompleteQuery(activeEditorState) }
-                        selection={this.getSelectionRange(activeEditorState)}
-                    />
-                </div>
-                <div className={className}>
-                    <AccessibleButton className={markdownClasses}
-                        onClick={this.onMarkdownToggleClicked}
-                        title={this.state.isRichTextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")}
-                    />
-                    <Editor ref={this._collectEditor}
-                            dir="auto"
-                            className="mx_MessageComposer_editor"
-                            placeholder={placeholder}
-                            value={this.state.editorState}
-                            onChange={this.onChange}
-                            onKeyDown={this.onKeyDown}
-                            onPaste={this.onPaste}
-                            renderNode={this.renderNode}
-                            renderMark={this.renderMark}
-                            // disable spell check for the placeholder because browsers don't like "unencrypted"
-                            spellCheck={!isEmpty}
-                            schema={SLATE_SCHEMA}
-                            />
-                </div>
-            </div>
-        );
-    }
-}
diff --git a/src/components/views/rooms/SlateMessageComposer.js b/src/components/views/rooms/SlateMessageComposer.js
deleted file mode 100644
index b1f7adbe32..0000000000
--- a/src/components/views/rooms/SlateMessageComposer.js
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-Copyright 2017, 2018 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import React, {createRef} from 'react';
-import PropTypes from 'prop-types';
-import { _t, _td } from '../../../languageHandler';
-import CallHandler from '../../../CallHandler';
-import {MatrixClientPeg} from '../../../MatrixClientPeg';
-import * as sdk from '../../../index';
-import dis from '../../../dispatcher';
-import RoomViewStore from '../../../stores/RoomViewStore';
-import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
-import Stickerpicker from './Stickerpicker';
-import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
-import ContentMessages from '../../../ContentMessages';
-
-import E2EIcon from './E2EIcon';
-
-const formatButtonList = [
-    _td("bold"),
-    _td("italic"),
-    _td("deleted"),
-    _td("underlined"),
-    _td("inline-code"),
-    _td("block-quote"),
-    _td("bulleted-list"),
-    _td("numbered-list"),
-];
-
-function ComposerAvatar(props) {
-    const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar');
-    return <div className="mx_MessageComposer_avatar">
-        <MemberStatusMessageAvatar member={props.me} width={24} height={24} />
-    </div>;
-}
-
-ComposerAvatar.propTypes = {
-    me: PropTypes.object.isRequired,
-}
-
-function CallButton(props) {
-    const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-    const onVoiceCallClick = (ev) => {
-        dis.dispatch({
-            action: 'place_call',
-            type: "voice",
-            room_id: props.roomId,
-        });
-    };
-
-    return <AccessibleButton className="mx_MessageComposer_button mx_MessageComposer_voicecall"
-        onClick={onVoiceCallClick}
-        title={_t('Voice call')}
-    />
-}
-
-CallButton.propTypes = {
-    roomId: PropTypes.string.isRequired
-}
-
-function VideoCallButton(props) {
-    const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-    const onCallClick = (ev) => {
-        dis.dispatch({
-            action: 'place_call',
-            type: ev.shiftKey ? "screensharing" : "video",
-            room_id: props.roomId,
-        });
-    };
-
-    return <AccessibleButton className="mx_MessageComposer_button mx_MessageComposer_videocall"
-        onClick={onCallClick}
-        title={_t('Video call')}
-    />;
-}
-
-VideoCallButton.propTypes = {
-    roomId: PropTypes.string.isRequired,
-};
-
-function HangupButton(props) {
-    const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-    const onHangupClick = () => {
-        const call = CallHandler.getCallForRoom(props.roomId);
-        if (!call) {
-            return;
-        }
-        dis.dispatch({
-            action: 'hangup',
-            // hangup the call for this room, which may not be the room in props
-            // (e.g. conferences which will hangup the 1:1 room instead)
-            room_id: call.roomId,
-        });
-    };
-    return  <AccessibleButton className="mx_MessageComposer_button mx_MessageComposer_hangup"
-        onClick={onHangupClick}
-        title={_t('Hangup')}
-    />;
-}
-
-HangupButton.propTypes = {
-    roomId: PropTypes.string.isRequired,
-}
-
-function FormattingButton(props) {
-    const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-    return <AccessibleButton
-        element="img"
-        className="mx_MessageComposer_formatting"
-        alt={_t("Show Text Formatting Toolbar")}
-        title={_t("Show Text Formatting Toolbar")}
-        src={require("../../../../res/img/button-text-formatting.svg")}
-        style={{visibility: props.showFormatting ? 'hidden' : 'visible'}}
-        onClick={props.onClickHandler}
-    />;
-}
-
-FormattingButton.propTypes = {
-    showFormatting: PropTypes.bool.isRequired,
-    onClickHandler: PropTypes.func.isRequired,
-}
-
-class UploadButton extends React.Component {
-    static propTypes = {
-        roomId: PropTypes.string.isRequired,
-    }
-    constructor(props, context) {
-        super(props, context);
-        this.onUploadClick = this.onUploadClick.bind(this);
-        this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
-
-        this._uploadInput = createRef();
-    }
-
-    onUploadClick(ev) {
-        if (MatrixClientPeg.get().isGuest()) {
-            dis.dispatch({action: 'require_registration'});
-            return;
-        }
-        this._uploadInput.current.click();
-    }
-
-    onUploadFileInputChange(ev) {
-        if (ev.target.files.length === 0) return;
-
-        // take a copy so we can safely reset the value of the form control
-        // (Note it is a FileList: we can't use slice or sesnible iteration).
-        const tfiles = [];
-        for (let i = 0; i < ev.target.files.length; ++i) {
-            tfiles.push(ev.target.files[i]);
-        }
-
-        ContentMessages.sharedInstance().sendContentListToRoom(
-            tfiles, this.props.roomId, MatrixClientPeg.get(),
-        );
-
-        // This is the onChange handler for a file form control, but we're
-        // not keeping any state, so reset the value of the form control
-        // to empty.
-        // NB. we need to set 'value': the 'files' property is immutable.
-        ev.target.value = '';
-    }
-
-    render() {
-        const uploadInputStyle = {display: 'none'};
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-        return (
-            <AccessibleButton className="mx_MessageComposer_button mx_MessageComposer_upload"
-                onClick={this.onUploadClick}
-                title={_t('Upload file')}
-            >
-                <input ref={this._uploadInput} type="file"
-                    style={uploadInputStyle}
-                    multiple
-                    onChange={this.onUploadFileInputChange}
-                />
-            </AccessibleButton>
-        );
-    }
-}
-
-export default class SlateMessageComposer extends React.Component {
-    constructor(props, context) {
-        super(props, context);
-        this._onAutocompleteConfirm = this._onAutocompleteConfirm.bind(this);
-        this.onToggleFormattingClicked = this.onToggleFormattingClicked.bind(this);
-        this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this);
-        this.onInputStateChanged = this.onInputStateChanged.bind(this);
-        this.onEvent = this.onEvent.bind(this);
-        this._onRoomStateEvents = this._onRoomStateEvents.bind(this);
-        this._onRoomViewStoreUpdate = this._onRoomViewStoreUpdate.bind(this);
-        this._onTombstoneClick = this._onTombstoneClick.bind(this);
-        this.renderPlaceholderText = this.renderPlaceholderText.bind(this);
-        this.renderFormatBar = this.renderFormatBar.bind(this);
-
-        this.state = {
-            inputState: {
-                marks: [],
-                blockType: null,
-                isRichTextEnabled: SettingsStore.getValue('MessageComposerInput.isRichTextEnabled'),
-            },
-            showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'),
-            isQuoting: Boolean(RoomViewStore.getQuotingEvent()),
-            tombstone: this._getRoomTombstone(),
-            canSendMessages: this.props.room.maySendMessage(),
-        };
-    }
-
-    componentDidMount() {
-        // N.B. using 'event' rather than 'RoomEvents' otherwise the crypto handler
-        // for 'event' fires *after* 'RoomEvent', and our room won't have yet been
-        // marked as encrypted.
-        // XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something.
-        MatrixClientPeg.get().on("event", this.onEvent);
-        MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents);
-        this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
-        this._waitForOwnMember();
-    }
-
-    _waitForOwnMember() {
-        // if we have the member already, do that
-        const me = this.props.room.getMember(MatrixClientPeg.get().getUserId());
-        if (me) {
-            this.setState({me});
-            return;
-        }
-        // Otherwise, wait for member loading to finish and then update the member for the avatar.
-        // The members should already be loading, and loadMembersIfNeeded
-        // will return the promise for the existing operation
-        this.props.room.loadMembersIfNeeded().then(() => {
-            const me = this.props.room.getMember(MatrixClientPeg.get().getUserId());
-            this.setState({me});
-        });
-    }
-
-    componentWillUnmount() {
-        if (MatrixClientPeg.get()) {
-            MatrixClientPeg.get().removeListener("event", this.onEvent);
-            MatrixClientPeg.get().removeListener("RoomState.events", this._onRoomStateEvents);
-        }
-        if (this._roomStoreToken) {
-            this._roomStoreToken.remove();
-        }
-    }
-
-    onEvent(event) {
-        if (event.getType() !== 'm.room.encryption') return;
-        if (event.getRoomId() !== this.props.room.roomId) return;
-        this.forceUpdate();
-    }
-
-    _onRoomStateEvents(ev, state) {
-        if (ev.getRoomId() !== this.props.room.roomId) return;
-
-        if (ev.getType() === 'm.room.tombstone') {
-            this.setState({tombstone: this._getRoomTombstone()});
-        }
-        if (ev.getType() === 'm.room.power_levels') {
-            this.setState({canSendMessages: this.props.room.maySendMessage()});
-        }
-    }
-
-    _getRoomTombstone() {
-        return this.props.room.currentState.getStateEvents('m.room.tombstone', '');
-    }
-
-    _onRoomViewStoreUpdate() {
-        const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
-        if (this.state.isQuoting === isQuoting) return;
-        this.setState({ isQuoting });
-    }
-
-
-    onInputStateChanged(inputState) {
-        // Merge the new input state with old to support partial updates
-        inputState = Object.assign({}, this.state.inputState, inputState);
-        this.setState({inputState});
-    }
-
-    _onAutocompleteConfirm(range, completion) {
-        if (this.messageComposerInput) {
-            this.messageComposerInput.setDisplayedCompletion(range, completion);
-        }
-    }
-
-    onFormatButtonClicked(name, event) {
-        event.preventDefault();
-        this.messageComposerInput.onFormatButtonClicked(name, event);
-    }
-
-    onToggleFormattingClicked() {
-        SettingsStore.setValue("MessageComposer.showFormatting", null, SettingLevel.DEVICE, !this.state.showFormatting);
-        this.setState({showFormatting: !this.state.showFormatting});
-    }
-
-    onToggleMarkdownClicked(e) {
-        e.preventDefault(); // don't steal focus from the editor!
-        this.messageComposerInput.enableRichtext(!this.state.inputState.isRichTextEnabled);
-    }
-
-    _onTombstoneClick(ev) {
-        ev.preventDefault();
-
-        const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
-        const replacementRoom = MatrixClientPeg.get().getRoom(replacementRoomId);
-        let createEventId = null;
-        if (replacementRoom) {
-            const createEvent = replacementRoom.currentState.getStateEvents('m.room.create', '');
-            if (createEvent && createEvent.getId()) createEventId = createEvent.getId();
-        }
-
-        const viaServers = [this.state.tombstone.getSender().split(':').splice(1).join(':')];
-        dis.dispatch({
-            action: 'view_room',
-            highlighted: true,
-            event_id: createEventId,
-            room_id: replacementRoomId,
-            auto_join: true,
-
-            // Try to join via the server that sent the event. This converts @something:example.org
-            // into a server domain by splitting on colons and ignoring the first entry ("@something").
-            via_servers: viaServers,
-            opts: {
-                // These are passed down to the js-sdk's /join call
-                viaServers: viaServers,
-            },
-        });
-    }
-
-    renderPlaceholderText() {
-        const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
-        if (this.state.isQuoting) {
-            if (roomIsEncrypted) {
-                return _t('Send an encrypted reply…');
-            } else {
-                return _t('Send a reply (unencrypted)…');
-            }
-        } else {
-            if (roomIsEncrypted) {
-                return _t('Send an encrypted message…');
-            } else {
-                return _t('Send a message (unencrypted)…');
-            }
-        }
-    }
-
-    renderFormatBar() {
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-        const {marks, blockType} = this.state.inputState;
-        const formatButtons = formatButtonList.map((name) => {
-            // special-case to match the md serializer and the special-case in MessageComposerInput.js
-            const markName = name === 'inline-code' ? 'code' : name;
-            const active = marks.some(mark => mark.type === markName) || blockType === name;
-            const suffix = active ? '-on' : '';
-            const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name);
-            const className = 'mx_MessageComposer_format_button mx_filterFlipColor';
-            return (
-                <img className={className}
-                    title={_t(name)}
-                    onMouseDown={onFormatButtonClicked}
-                    key={name}
-                    src={require(`../../../../res/img/button-text-${name}${suffix}.svg`)}
-                    height="17"
-                />
-            );
-        })
-
-        return (
-            <div className="mx_MessageComposer_formatbar_wrapper">
-                <div className="mx_MessageComposer_formatbar">
-                { formatButtons }
-                <div style={{ flex: 1 }}></div>
-                <AccessibleButton
-                    className="mx_MessageComposer_formatbar_markdown mx_MessageComposer_markdownDisabled"
-                    onClick={this.onToggleMarkdownClicked}
-                    title={_t("Markdown is disabled")}
-                />
-                <AccessibleButton element="img" title={_t("Hide Text Formatting Toolbar")}
-                    onClick={this.onToggleFormattingClicked}
-                    className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
-                    src={require("../../../../res/img/icon-text-cancel.svg")}
-                />
-                </div>
-            </div>
-        );
-    }
-
-    render() {
-        const controls = [
-            this.state.me ? <ComposerAvatar key="controls_avatar" me={this.state.me} /> : null,
-            this.props.e2eStatus ? <E2EIcon key="e2eIcon" status={this.props.e2eStatus} className="mx_MessageComposer_e2eIcon" /> : null,
-        ];
-
-        if (!this.state.tombstone && this.state.canSendMessages) {
-            // This also currently includes the call buttons. Really we should
-            // check separately for whether we can call, but this is slightly
-            // complex because of conference calls.
-
-            const MessageComposerInput = sdk.getComponent("rooms.MessageComposerInput");
-            const showFormattingButton = this.state.inputState.isRichTextEnabled;
-            const callInProgress = this.props.callState && this.props.callState !== 'ended';
-
-            controls.push(
-                <MessageComposerInput
-                    ref={(c) => this.messageComposerInput = c}
-                    key="controls_input"
-                    room={this.props.room}
-                    placeholder={this.renderPlaceholderText()}
-                    onInputStateChanged={this.onInputStateChanged}
-                    permalinkCreator={this.props.permalinkCreator} />,
-                showFormattingButton ? <FormattingButton key="controls_formatting"
-                    showFormatting={this.state.showFormatting} onClickHandler={this.onToggleFormattingClicked} /> : null,
-                <Stickerpicker key='stickerpicker_controls_button' room={this.props.room} />,
-                <UploadButton key="controls_upload" roomId={this.props.room.roomId} />,
-                callInProgress ? <HangupButton key="controls_hangup" roomId={this.props.room.roomId} /> : null,
-                callInProgress ? null : <CallButton key="controls_call" roomId={this.props.room.roomId} />,
-                callInProgress ? null : <VideoCallButton key="controls_videocall" roomId={this.props.room.roomId} />,
-            );
-        } else if (this.state.tombstone) {
-            const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
-
-            const continuesLink = replacementRoomId ? (
-                <a href={makeRoomPermalink(replacementRoomId)}
-                    className="mx_MessageComposer_roomReplaced_link"
-                    onClick={this._onTombstoneClick}
-                >
-                    {_t("The conversation continues here.")}
-                </a>
-            ) : '';
-
-            controls.push(<div className="mx_MessageComposer_replaced_wrapper">
-                <div className="mx_MessageComposer_replaced_valign">
-                    <img className="mx_MessageComposer_roomReplaced_icon" src={require("../../../../res/img/room_replaced.svg")} />
-                    <span className="mx_MessageComposer_roomReplaced_header">
-                        {_t("This room has been replaced and is no longer active.")}
-                    </span><br />
-                    { continuesLink }
-                </div>
-            </div>);
-        } else {
-            controls.push(
-                <div key="controls_error" className="mx_MessageComposer_noperm_error">
-                    { _t('You do not have permission to post to this room') }
-                </div>,
-            );
-        }
-
-        const showFormatBar = this.state.showFormatting && this.state.inputState.isRichTextEnabled;
-
-        return (
-            <div className="mx_MessageComposer">
-                <div className="mx_MessageComposer_wrapper">
-                    <div className="mx_MessageComposer_row">
-                        { controls }
-                    </div>
-                </div>
-                { showFormatBar ? this.renderFormatBar() : null }
-            </div>
-        );
-    }
-}
-
-SlateMessageComposer.propTypes = {
-    // js-sdk Room object
-    room: PropTypes.object.isRequired,
-
-    // string representing the current voip call state
-    callState: PropTypes.string,
-
-    // string representing the current room app drawer state
-    showApps: PropTypes.bool
-};
diff --git a/src/stores/MessageComposerStore.js b/src/stores/MessageComposerStore.js
deleted file mode 100644
index 3c7440e10b..0000000000
--- a/src/stores/MessageComposerStore.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-Copyright 2017, 2018 Vector Creations Ltd
-Copyright 2019 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import { Value } from 'slate';
-
-const localStoragePrefix = 'editor_state_';
-
-/**
- * A class for storing application state to do with the message composer (specifically in-progress message drafts).
- * It does not worry about cleaning up on log out as this is handled in Lifecycle.js by localStorage.clear()
- */
-class MessageComposerStore {
-    constructor() {
-        this.prefix = localStoragePrefix;
-    }
-
-    _getKey(roomId: string): string {
-        return this.prefix + roomId;
-    }
-
-    setEditorState(roomId: string, editorState: Value, richText: boolean) {
-        localStorage.setItem(this._getKey(roomId), JSON.stringify({
-            editor_state: editorState.toJSON({
-                preserveSelection: true,
-                // XXX: re-hydrating history is not currently supported by fromJSON
-                // preserveHistory: true,
-                // XXX: this seems like a workaround for selection.isSet being based on anchorKey instead of anchorPath
-                preserveKeys: true,
-            }),
-            rich_text: richText,
-        }));
-    }
-
-    getEditorState(roomId): {editor_state: Value, rich_text: boolean} {
-        const stateStr = localStorage.getItem(this._getKey(roomId));
-
-        let state;
-        if (stateStr) {
-            state = JSON.parse(stateStr);
-
-            // if it does not have the fields we expect then bail
-            if (!state || state.rich_text === undefined || state.editor_state === undefined) return;
-            state.editor_state = Value.fromJSON(state.editor_state);
-        }
-
-        return state;
-    }
-}
-
-let singletonMessageComposerStore = null;
-if (!singletonMessageComposerStore) {
-    singletonMessageComposerStore = new MessageComposerStore();
-}
-export default singletonMessageComposerStore;
diff --git a/test/components/views/rooms/MessageComposerInput-test.js b/test/components/views/rooms/MessageComposerInput-test.js
deleted file mode 100644
index 6adae13181..0000000000
--- a/test/components/views/rooms/MessageComposerInput-test.js
+++ /dev/null
@@ -1,303 +0,0 @@
-import React from 'react';
-import ReactTestUtils from 'react-dom/test-utils';
-import ReactDOM from 'react-dom';
-import expect from 'expect';
-import sinon from 'sinon';
-import * as testUtils from '../../../test-utils';
-import sdk from 'matrix-react-sdk';
-const MessageComposerInput = sdk.getComponent('views.rooms.MessageComposerInput');
-import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
-import {sleep} from "../../../../src/utils/promise";
-
-function addTextToDraft(text) {
-    const components = document.getElementsByClassName('public-DraftEditor-content');
-    if (components && components.length) {
-        const textarea = components[0];
-        const textEvent = document.createEvent('TextEvent');
-        textEvent.initTextEvent('textInput', true, true, null, text);
-        textarea.dispatchEvent(textEvent);
-    }
-}
-
-// FIXME: These tests need to be updated from Draft to Slate.
-
-xdescribe('MessageComposerInput', () => {
-    let parentDiv = null,
-        sandbox = null,
-        client = null,
-        mci = null,
-        room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
-
-    beforeEach(function() {
-        testUtils.beforeEach(this);
-        sandbox = testUtils.stubClient(sandbox);
-        client = MatrixClientPeg.get();
-        client.credentials = {userId: '@me:domain.com'};
-
-        parentDiv = document.createElement('div');
-        document.body.appendChild(parentDiv);
-        mci = ReactDOM.render(
-            <MessageComposerInput
-                room={room}
-                client={client}
-            />,
-            parentDiv);
-    });
-
-    afterEach((done) => {
-        // hack: let the component finish mounting before unmounting, to avoid
-        // warnings
-        // (please can we make the components not setState() after
-        // they are unmounted?)
-        sleep(10).done(() => {
-            if (parentDiv) {
-                ReactDOM.unmountComponentAtNode(parentDiv);
-                parentDiv.remove();
-                parentDiv = null;
-            }
-            sandbox.restore();
-            done();
-        });
-    });
-
-    // XXX this fails
-    xit('should change mode if indicator is clicked', (done) => {
-        mci.enableRichtext(true);
-
-        setTimeout(() => {
-            const indicator = ReactTestUtils.findRenderedDOMComponentWithClass(
-                mci,
-                'mx_MessageComposer_input_markdownIndicator');
-            ReactTestUtils.Simulate.click(indicator);
-
-            expect(mci.state.isRichTextEnabled).toEqual(false, 'should have changed mode');
-            done();
-        });
-    });
-
-    it('should not send messages when composer is empty', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(true);
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(false, 'should not send message');
-    });
-
-    it('should not change content unnecessarily on RTE -> Markdown conversion', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(true);
-        addTextToDraft('a');
-        mci.handleKeyCommand('toggle-mode');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('a');
-    });
-
-    it('should not change content unnecessarily on Markdown -> RTE conversion', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('a');
-        mci.handleKeyCommand('toggle-mode');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('a');
-    });
-
-    it('should send emoji messages when rich text is enabled', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(true);
-        addTextToDraft('☹');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true, 'should send message');
-    });
-
-    it('should send emoji messages when Markdown is enabled', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('☹');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true, 'should send message');
-    });
-
-    // FIXME
-    // it('should convert basic Markdown to rich text correctly', () => {
-    //     const spy = sinon.spy(client, 'sendHtmlMessage');
-    //     mci.enableRichtext(false);
-    //     addTextToDraft('*abc*');
-    //     mci.handleKeyCommand('toggle-mode');
-    //     mci.handleReturn(sinon.stub());
-    //     console.error(spy.args[0][2]);
-    //     expect(spy.args[0][2]).toContain('<em>abc');
-    // });
-    //
-    // it('should convert basic rich text to Markdown correctly', () => {
-    //     const spy = sinon.spy(client, 'sendHtmlMessage');
-    //     mci.enableRichtext(true);
-    //     process.nextTick(() => {
-    //
-    //     });
-    //     mci.handleKeyCommand('italic');
-    //     addTextToDraft('abc');
-    //     mci.handleKeyCommand('toggle-mode');
-    //     mci.handleReturn(sinon.stub());
-    //     expect(['_abc_', '*abc*']).toContain(spy.args[0][1]);
-    // });
-
-    it('should insert formatting characters in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        mci.handleKeyCommand('italic');
-        mci.handleReturn(sinon.stub());
-        expect(['__', '**']).toContain(spy.args[0][1].body);
-    });
-
-    it('should not entity-encode " in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('"');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('"');
-    });
-
-    it('should escape characters without other markup in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('\\*escaped\\*');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('*escaped*');
-    });
-
-    it('should escape characters with other markup in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('\\*escaped\\* *italic*');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('\\*escaped\\* *italic*');
-        expect(spy.args[0][1].formatted_body).toEqual('*escaped* <em>italic</em>');
-    });
-
-    it('should not convert -_- into a horizontal rule in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('-_-');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('-_-');
-    });
-
-    it('should not strip <del> tags in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('<del>striked-out</del>');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('<del>striked-out</del>');
-        expect(spy.args[0][1].formatted_body).toEqual('<del>striked-out</del>');
-    });
-
-    it('should not strike-through ~~~ in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('~~~striked-out~~~');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('~~~striked-out~~~');
-    });
-
-    it('should not mark single unmarkedup paragraphs as HTML in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
-    });
-
-    it('should not mark two unmarkedup paragraphs as HTML in Markdown mode', () => {
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        addTextToDraft('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nFusce congue sapien sed neque molestie volutpat.');
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.calledOnce).toEqual(true);
-        expect(spy.args[0][1].body).toEqual('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nFusce congue sapien sed neque molestie volutpat.');
-    });
-
-    it('should strip tab-completed mentions so that only the display name is sent in the plain body in Markdown mode', () => {
-        // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(false);
-        mci.setDisplayedCompletion({
-            completion: 'Some Member',
-            selection: mci.state.editorState.getSelection(),
-            href: `https://matrix.to/#/@some_member:domain.bla`,
-        });
-
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.args[0][1].body).toEqual(
-            'Some Member',
-            'the plaintext body should only include the display name',
-        );
-        expect(spy.args[0][1].formatted_body).toEqual(
-            '<a href="https://matrix.to/#/@some_member:domain.bla">Some Member</a>',
-            'the html body should contain an anchor tag with a matrix.to href and display name text',
-        );
-    });
-
-    it('should strip tab-completed mentions so that only the display name is sent in the plain body in RTE mode', () => {
-        // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
-        mci.enableRichtext(true);
-        mci.setDisplayedCompletion({
-            completion: 'Some Member',
-            selection: mci.state.editorState.getSelection(),
-            href: `https://matrix.to/#/@some_member:domain.bla`,
-        });
-
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.args[0][1].body).toEqual('Some Member');
-        expect(spy.args[0][1].formatted_body).toEqual('<a href="https://matrix.to/#/@some_member:domain.bla">Some Member</a>');
-    });
-
-    it('should not strip non-tab-completed mentions when manually typing MD', () => {
-        // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
-        // Markdown mode enabled
-        mci.enableRichtext(false);
-        addTextToDraft('[My Not-Tab-Completed Mention](https://matrix.to/#/@some_member:domain.bla)');
-
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.args[0][1].body).toEqual('[My Not-Tab-Completed Mention](https://matrix.to/#/@some_member:domain.bla)');
-        expect(spy.args[0][1].formatted_body).toEqual('<a href="https://matrix.to/#/@some_member:domain.bla">My Not-Tab-Completed Mention</a>');
-    });
-
-    it('should not strip arbitrary typed (i.e. not tab-completed) MD links', () => {
-        // Sending a HTML message because we have entities in the composer (because of completions)
-        const spy = sinon.spy(client, 'sendMessage');
-        // Markdown mode enabled
-        mci.enableRichtext(false);
-        addTextToDraft('[Click here](https://some.lovely.url)');
-
-        mci.handleReturn(sinon.stub());
-
-        expect(spy.args[0][1].body).toEqual('[Click here](https://some.lovely.url)');
-        expect(spy.args[0][1].formatted_body).toEqual('<a href="https://some.lovely.url">Click here</a>');
-    });
-});

From 135c84251c8b7b5c7f02dd81d6b914e99ec1b247 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 14:16:32 -0700
Subject: [PATCH 58/86] Fix more imports post-merge

---
 src/components/views/context_menus/TopLeftMenu.js         | 2 +-
 src/components/views/dialogs/DMInviteDialog.js            | 8 ++++----
 src/components/views/elements/ToggleSwitch.js             | 3 +--
 src/components/views/room_settings/RoomProfileSettings.js | 2 +-
 src/components/views/rooms/RoomList.js                    | 2 +-
 src/components/views/settings/AvatarSetting.js            | 2 +-
 src/components/views/settings/ProfileSettings.js          | 2 +-
 .../views/settings/tabs/room/BridgeSettingsTab.js         | 8 ++++----
 src/utils/DMRoomMap.js                                    | 2 +-
 9 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js
index 4f6da336f7..528e4790c2 100644
--- a/src/components/views/context_menus/TopLeftMenu.js
+++ b/src/components/views/context_menus/TopLeftMenu.js
@@ -25,7 +25,7 @@ import SdkConfig from '../../../SdkConfig';
 import { getHostingLink } from '../../../utils/HostingLink';
 import {MatrixClientPeg} from '../../../MatrixClientPeg';
 import {MenuItem} from "../../structures/ContextMenu";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export class TopLeftMenu extends React.Component {
     static propTypes = {
diff --git a/src/components/views/dialogs/DMInviteDialog.js b/src/components/views/dialogs/DMInviteDialog.js
index 371768eb4e..a0d95772f9 100644
--- a/src/components/views/dialogs/DMInviteDialog.js
+++ b/src/components/views/dialogs/DMInviteDialog.js
@@ -17,14 +17,14 @@ limitations under the License.
 import React, {createRef} from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
-import sdk from "../../../index";
-import MatrixClientPeg from "../../../MatrixClientPeg";
+import * as sdk from "../../../index";
+import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import {makeUserPermalink} from "../../../utils/permalinks/Permalinks";
 import DMRoomMap from "../../../utils/DMRoomMap";
-import {RoomMember} from "matrix-js-sdk/lib/matrix";
+import {RoomMember} from "matrix-js-sdk/src/matrix";
 import * as humanize from "humanize";
 import SdkConfig from "../../../SdkConfig";
-import {getHttpUriForMxc} from "matrix-js-sdk/lib/content-repo";
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 import * as Email from "../../../email";
 import {getDefaultIdentityServerUrl, useDefaultIdentityServer} from "../../../utils/IdentityServerUtils";
 import {abbreviateUrl} from "../../../utils/UrlUtils";
diff --git a/src/components/views/elements/ToggleSwitch.js b/src/components/views/elements/ToggleSwitch.js
index b067840792..bea1a85555 100644
--- a/src/components/views/elements/ToggleSwitch.js
+++ b/src/components/views/elements/ToggleSwitch.js
@@ -18,8 +18,7 @@ limitations under the License.
 import React from "react";
 import PropTypes from "prop-types";
 import classNames from "classnames";
-
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 // Controlled Toggle Switch element, written with Accessibility in mind
 const ToggleSwitch = ({checked, disabled=false, onChange, ...props}) => {
diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.js
index 2b0123192c..a1816df71a 100644
--- a/src/components/views/room_settings/RoomProfileSettings.js
+++ b/src/components/views/room_settings/RoomProfileSettings.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Field from "../elements/Field";
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 // TODO: Merge with ProfileSettings?
 export default class RoomProfileSettings extends React.Component {
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index b33e3daf77..5c12b027a4 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -21,7 +21,7 @@ import React from "react";
 import ReactDOM from "react-dom";
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
-import utils from "matrix-js-sdk/lib/utils";
+import * as utils from "matrix-js-sdk/src/utils";
 import { _t } from '../../../languageHandler';
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import rate_limited_func from "../../../ratelimitedfunc";
diff --git a/src/components/views/settings/AvatarSetting.js b/src/components/views/settings/AvatarSetting.js
index 51ef3a4302..261a832158 100644
--- a/src/components/views/settings/AvatarSetting.js
+++ b/src/components/views/settings/AvatarSetting.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React, {useCallback} from "react";
 import PropTypes from "prop-types";
 
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 import {_t} from "../../../languageHandler";
 import Modal from "../../../Modal";
 
diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js
index e386b0fe0f..8d2c289b15 100644
--- a/src/components/views/settings/ProfileSettings.js
+++ b/src/components/views/settings/ProfileSettings.js
@@ -20,7 +20,7 @@ import {MatrixClientPeg} from "../../../MatrixClientPeg";
 import Field from "../elements/Field";
 import {User} from "matrix-js-sdk";
 import { getHostingLink } from '../../../utils/HostingLink';
-import sdk from "../../../index";
+import * as sdk from "../../../index";
 
 export default class ProfileSettings extends React.Component {
     constructor() {
diff --git a/src/components/views/settings/tabs/room/BridgeSettingsTab.js b/src/components/views/settings/tabs/room/BridgeSettingsTab.js
index 3022885701..71b0169788 100644
--- a/src/components/views/settings/tabs/room/BridgeSettingsTab.js
+++ b/src/components/views/settings/tabs/room/BridgeSettingsTab.js
@@ -17,11 +17,11 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import {_t} from "../../../../../languageHandler";
-import MatrixClientPeg from "../../../../../MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import Pill from "../../../elements/Pill";
 import {makeUserPermalink} from "../../../../../utils/permalinks/Permalinks";
 import BaseAvatar from "../../../avatars/BaseAvatar";
-import { ContentRepo } from "matrix-js-sdk";
+import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 const BRIDGE_EVENT_TYPES = [
     "uk.half-shot.bridge",
@@ -83,7 +83,7 @@ export default class BridgeSettingsTab extends React.Component {
 
         let networkIcon = null;
         if (networkName && network.avatar) {
-            const avatarUrl = ContentRepo.getHttpUriForMxc(
+            const avatarUrl = getHttpUriForMxc(
                 MatrixClientPeg.get().getHomeserverUrl(),
                 network.avatar, 32, 32, "crop",
             );
@@ -99,7 +99,7 @@ export default class BridgeSettingsTab extends React.Component {
 
         let channelIcon = null;
         if (channel.avatar) {
-            const avatarUrl = ContentRepo.getHttpUriForMxc(
+            const avatarUrl = getHttpUriForMxc(
                 MatrixClientPeg.get().getHomeserverUrl(),
                 channel.avatar, 32, 32, "crop",
             );
diff --git a/src/utils/DMRoomMap.js b/src/utils/DMRoomMap.js
index fb66b0a55f..547da0863b 100644
--- a/src/utils/DMRoomMap.js
+++ b/src/utils/DMRoomMap.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 import {MatrixClientPeg} from '../MatrixClientPeg';
 import _uniq from 'lodash/uniq';
-import {Room} from "matrix-js-sdk/lib/matrix";
+import {Room} from "matrix-js-sdk/src/matrix";
 
 /**
  * Class that takes a Matrix Client and flips the m.direct map

From 23eb6cbeb3a91c2d6dbbba1d3686faa26349b229 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 16:17:27 -0700
Subject: [PATCH 59/86] Upgrade Jest and babel-jest to match js-sdk

This also magically gets rid of a ton of errors
---
 package.json |    8 +-
 yarn.lock    | 1781 +++++++++++++++++++++-----------------------------
 2 files changed, 759 insertions(+), 1030 deletions(-)

diff --git a/package.json b/package.json
index d1603104b7..29567928f5 100644
--- a/package.json
+++ b/package.json
@@ -122,7 +122,7 @@
     "@babel/register": "^7.7.4",
     "@babel/runtime": "^7.7.6",
     "babel-eslint": "^10.0.3",
-    "babel-jest": "^23.6.0",
+    "babel-jest": "^24.9.0",
     "chokidar": "^2.1.2",
     "concurrently": "^4.0.1",
     "enzyme": "^3.10.0",
@@ -137,7 +137,7 @@
     "estree-walker": "^0.5.0",
     "file-loader": "^3.0.1",
     "flow-parser": "^0.57.3",
-    "jest": "^23.2.0",
+    "jest": "^24.9.0",
     "matrix-mock-request": "^1.2.3",
     "matrix-react-test-utils": "^0.2.2",
     "react-test-renderer": "^16.9.0",
@@ -155,7 +155,9 @@
     "webpack-cli": "^3.1.1"
   },
   "jest": {
-    "testMatch": ["<rootDir>/test/**/*-test.js"],
+    "testMatch": [
+      "<rootDir>/test/**/*-test.js"
+    ],
     "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
       "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"
diff --git a/yarn.lock b/yarn.lock
index bb185e316f..49c559a612 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -18,7 +18,7 @@
   optionalDependencies:
     chokidar "^2.1.8"
 
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35", "@babel/code-frame@^7.5.5":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
   version "7.5.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
   integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
@@ -45,6 +45,26 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
+"@babel/core@^7.1.0":
+  version "7.7.7"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9"
+  integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==
+  dependencies:
+    "@babel/code-frame" "^7.5.5"
+    "@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"
+    lodash "^4.17.13"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
 "@babel/core@^7.7.5":
   version "7.7.5"
   resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e"
@@ -65,6 +85,16 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
+"@babel/generator@^7.4.0", "@babel/generator@^7.7.7":
+  version "7.7.7"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45"
+  integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+    jsesc "^2.5.1"
+    lodash "^4.17.13"
+    source-map "^0.5.0"
+
 "@babel/generator@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
@@ -281,6 +311,11 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb"
   integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==
 
+"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.7":
+  version "7.7.7"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937"
+  integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==
+
 "@babel/parser@^7.7.5":
   version "7.7.5"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
@@ -424,7 +459,7 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
-"@babel/plugin-syntax-object-rest-spread@^7.7.4":
+"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46"
   integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==
@@ -873,7 +908,7 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
-"@babel/template@^7.7.4":
+"@babel/template@^7.4.0", "@babel/template@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
   integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==
@@ -882,7 +917,7 @@
     "@babel/parser" "^7.7.4"
     "@babel/types" "^7.7.4"
 
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.7.4":
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
   integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==
@@ -897,7 +932,7 @@
     globals "^11.1.0"
     lodash "^4.17.13"
 
-"@babel/types@^7.0.0", "@babel/types@^7.7.4":
+"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
   integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==
@@ -906,6 +941,162 @@
     lodash "^4.17.13"
     to-fast-properties "^2.0.0"
 
+"@cnakazawa/watch@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
+  integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==
+  dependencies:
+    exec-sh "^0.3.2"
+    minimist "^1.2.0"
+
+"@jest/console@^24.7.1", "@jest/console@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0"
+  integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==
+  dependencies:
+    "@jest/source-map" "^24.9.0"
+    chalk "^2.0.1"
+    slash "^2.0.0"
+
+"@jest/core@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4"
+  integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/reporters" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/transform" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    graceful-fs "^4.1.15"
+    jest-changed-files "^24.9.0"
+    jest-config "^24.9.0"
+    jest-haste-map "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve "^24.9.0"
+    jest-resolve-dependencies "^24.9.0"
+    jest-runner "^24.9.0"
+    jest-runtime "^24.9.0"
+    jest-snapshot "^24.9.0"
+    jest-util "^24.9.0"
+    jest-validate "^24.9.0"
+    jest-watcher "^24.9.0"
+    micromatch "^3.1.10"
+    p-each-series "^1.0.0"
+    realpath-native "^1.1.0"
+    rimraf "^2.5.4"
+    slash "^2.0.0"
+    strip-ansi "^5.0.0"
+
+"@jest/environment@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18"
+  integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==
+  dependencies:
+    "@jest/fake-timers" "^24.9.0"
+    "@jest/transform" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    jest-mock "^24.9.0"
+
+"@jest/fake-timers@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93"
+  integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==
+  dependencies:
+    "@jest/types" "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-mock "^24.9.0"
+
+"@jest/reporters@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43"
+  integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==
+  dependencies:
+    "@jest/environment" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/transform" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    glob "^7.1.2"
+    istanbul-lib-coverage "^2.0.2"
+    istanbul-lib-instrument "^3.0.1"
+    istanbul-lib-report "^2.0.4"
+    istanbul-lib-source-maps "^3.0.1"
+    istanbul-reports "^2.2.6"
+    jest-haste-map "^24.9.0"
+    jest-resolve "^24.9.0"
+    jest-runtime "^24.9.0"
+    jest-util "^24.9.0"
+    jest-worker "^24.6.0"
+    node-notifier "^5.4.2"
+    slash "^2.0.0"
+    source-map "^0.6.0"
+    string-length "^2.0.0"
+
+"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714"
+  integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==
+  dependencies:
+    callsites "^3.0.0"
+    graceful-fs "^4.1.15"
+    source-map "^0.6.0"
+
+"@jest/test-result@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca"
+  integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==
+  dependencies:
+    "@jest/console" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    "@types/istanbul-lib-coverage" "^2.0.0"
+
+"@jest/test-sequencer@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31"
+  integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==
+  dependencies:
+    "@jest/test-result" "^24.9.0"
+    jest-haste-map "^24.9.0"
+    jest-runner "^24.9.0"
+    jest-runtime "^24.9.0"
+
+"@jest/transform@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56"
+  integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==
+  dependencies:
+    "@babel/core" "^7.1.0"
+    "@jest/types" "^24.9.0"
+    babel-plugin-istanbul "^5.1.0"
+    chalk "^2.0.1"
+    convert-source-map "^1.4.0"
+    fast-json-stable-stringify "^2.0.0"
+    graceful-fs "^4.1.15"
+    jest-haste-map "^24.9.0"
+    jest-regex-util "^24.9.0"
+    jest-util "^24.9.0"
+    micromatch "^3.1.10"
+    pirates "^4.0.1"
+    realpath-native "^1.1.0"
+    slash "^2.0.0"
+    source-map "^0.6.1"
+    write-file-atomic "2.4.1"
+
+"@jest/types@^24.9.0":
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59"
+  integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==
+  dependencies:
+    "@types/istanbul-lib-coverage" "^2.0.0"
+    "@types/istanbul-reports" "^1.1.1"
+    "@types/yargs" "^13.0.0"
+
 "@mrmlnc/readdir-enhanced@^2.2.1":
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -919,6 +1110,39 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
+"@types/babel__core@^7.1.0":
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
+  integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==
+  dependencies:
+    "@babel/parser" "^7.1.0"
+    "@babel/types" "^7.0.0"
+    "@types/babel__generator" "*"
+    "@types/babel__template" "*"
+    "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+  version "7.6.1"
+  resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04"
+  integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==
+  dependencies:
+    "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
+  integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==
+  dependencies:
+    "@babel/parser" "^7.1.0"
+    "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
+  version "7.0.8"
+  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012"
+  integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==
+  dependencies:
+    "@babel/types" "^7.3.0"
+
 "@types/events@*":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -933,6 +1157,26 @@
     "@types/minimatch" "*"
     "@types/node" "*"
 
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
+  integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
+
+"@types/istanbul-lib-report@*":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
+  integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
+  dependencies:
+    "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^1.1.1":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
+  integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
+  dependencies:
+    "@types/istanbul-lib-coverage" "*"
+    "@types/istanbul-lib-report" "*"
+
 "@types/json-schema@^7.0.3":
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
@@ -948,6 +1192,11 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2"
   integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==
 
+"@types/stack-utils@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
+  integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
+
 "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@@ -969,6 +1218,18 @@
     "@types/unist" "*"
     "@types/vfile-message" "*"
 
+"@types/yargs-parser@*":
+  version "13.1.0"
+  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228"
+  integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==
+
+"@types/yargs@^13.0.0":
+  version "13.0.5"
+  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.5.tgz#18121bfd39dc12f280cee58f92c5b21d32041908"
+  integrity sha512-CF/+sxTO7FOwbIRL4wMv0ZYLCRfMid2HQpzDRyViH7kSpfoAFiMdGqKIxb1PxWfjtQXQhnQuD33lvRHNwr809Q==
+  dependencies:
+    "@types/yargs-parser" "*"
+
 "@typescript-eslint/experimental-utils@^2.5.0":
   version "2.10.0"
   resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz#8db1656cdfd3d9dcbdbf360b8274dea76f0b2c2c"
@@ -1262,16 +1523,11 @@ ansi-regex@^3.0.0:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
   integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
 
-ansi-regex@^4.1.0:
+ansi-regex@^4.0.0, ansi-regex@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
   integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
 
-ansi-styles@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-  integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
 ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -1287,13 +1543,6 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-append-transform@^0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
-  integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
-  dependencies:
-    default-require-extensions "^1.0.0"
-
 aproba@^1.0.3, aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -1314,19 +1563,12 @@ argparse@^1.0.7:
   dependencies:
     sprintf-js "~1.0.2"
 
-arr-diff@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
-  integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
-  dependencies:
-    arr-flatten "^1.0.1"
-
 arr-diff@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
   integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
 
-arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+arr-flatten@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
   integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
@@ -1371,11 +1613,6 @@ array-uniq@^1.0.1, array-uniq@^1.0.2:
   resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
   integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
 
-array-unique@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
-  integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
 array-unique@^0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
@@ -1456,7 +1693,7 @@ async-limiter@~1.0.0:
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
   integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
 
-async@^2.1.4, async@^2.5.0:
+async@^2.5.0:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
   integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
@@ -1496,40 +1733,6 @@ aws4@^1.8.0:
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c"
   integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==
 
-babel-code-frame@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
-  integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
-  dependencies:
-    chalk "^1.1.3"
-    esutils "^2.0.2"
-    js-tokens "^3.0.2"
-
-babel-core@^6.0.0, babel-core@^6.26.0:
-  version "6.26.3"
-  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
-  integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-generator "^6.26.0"
-    babel-helpers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-register "^6.26.0"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    convert-source-map "^1.5.1"
-    debug "^2.6.9"
-    json5 "^0.5.1"
-    lodash "^4.17.4"
-    minimatch "^3.0.4"
-    path-is-absolute "^1.0.1"
-    private "^0.1.8"
-    slash "^1.0.0"
-    source-map "^0.5.7"
-
 babel-eslint@^10.0.3:
   version "10.0.3"
   resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a"
@@ -1542,42 +1745,18 @@ babel-eslint@^10.0.3:
     eslint-visitor-keys "^1.0.0"
     resolve "^1.12.0"
 
-babel-generator@^6.18.0, babel-generator@^6.26.0:
-  version "6.26.1"
-  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
-  integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+babel-jest@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54"
+  integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==
   dependencies:
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    detect-indent "^4.0.0"
-    jsesc "^1.3.0"
-    lodash "^4.17.4"
-    source-map "^0.5.7"
-    trim-right "^1.0.1"
-
-babel-helpers@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
-  integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-jest@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
-  integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
-  dependencies:
-    babel-plugin-istanbul "^4.1.6"
-    babel-preset-jest "^23.2.0"
-
-babel-messages@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
-  integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
-  dependencies:
-    babel-runtime "^6.22.0"
+    "@jest/transform" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    "@types/babel__core" "^7.1.0"
+    babel-plugin-istanbul "^5.1.0"
+    babel-preset-jest "^24.9.0"
+    chalk "^2.4.2"
+    slash "^2.0.0"
 
 babel-plugin-dynamic-import-node@^2.3.0:
   version "2.3.0"
@@ -1586,48 +1765,32 @@ babel-plugin-dynamic-import-node@^2.3.0:
   dependencies:
     object.assign "^4.1.0"
 
-babel-plugin-istanbul@^4.1.6:
-  version "4.1.6"
-  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
-  integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
+babel-plugin-istanbul@^5.1.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854"
+  integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==
   dependencies:
-    babel-plugin-syntax-object-rest-spread "^6.13.0"
-    find-up "^2.1.0"
-    istanbul-lib-instrument "^1.10.1"
-    test-exclude "^4.2.1"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    find-up "^3.0.0"
+    istanbul-lib-instrument "^3.3.0"
+    test-exclude "^5.2.3"
 
-babel-plugin-jest-hoist@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
-  integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
-
-babel-plugin-syntax-object-rest-spread@^6.13.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
-  integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
-
-babel-preset-jest@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
-  integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
+babel-plugin-jest-hoist@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756"
+  integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==
   dependencies:
-    babel-plugin-jest-hoist "^23.2.0"
-    babel-plugin-syntax-object-rest-spread "^6.13.0"
+    "@types/babel__traverse" "^7.0.6"
 
-babel-register@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
-  integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
+babel-preset-jest@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc"
+  integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==
   dependencies:
-    babel-core "^6.26.0"
-    babel-runtime "^6.26.0"
-    core-js "^2.5.0"
-    home-or-tmp "^2.0.0"
-    lodash "^4.17.4"
-    mkdirp "^0.5.1"
-    source-map-support "^0.4.15"
+    "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+    babel-plugin-jest-hoist "^24.9.0"
 
-babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -1635,47 +1798,6 @@ babel-runtime@^6.22.0, babel-runtime@^6.26.0:
     core-js "^2.4.0"
     regenerator-runtime "^0.11.0"
 
-babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
-  integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    lodash "^4.17.4"
-
-babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
-  integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    debug "^2.6.8"
-    globals "^9.18.0"
-    invariant "^2.2.2"
-    lodash "^4.17.4"
-
-babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
-  integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
-  dependencies:
-    babel-runtime "^6.26.0"
-    esutils "^2.0.2"
-    lodash "^4.17.4"
-    to-fast-properties "^1.0.3"
-
-babylon@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
-  integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
-
 bail@^1.0.0:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.4.tgz#7181b66d508aa3055d3f6c13f0a0c720641dde9b"
@@ -1728,13 +1850,6 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
-bindings@^1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
-  integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
-  dependencies:
-    file-uri-to-path "1.0.0"
-
 bluebird@^2.9.27:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
@@ -1768,15 +1883,6 @@ brace-expansion@^1.1.7:
     balanced-match "^1.0.0"
     concat-map "0.0.1"
 
-braces@^1.8.2:
-  version "1.8.5"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
-  integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
-  dependencies:
-    expand-range "^1.8.1"
-    preserve "^0.2.0"
-    repeat-element "^1.1.2"
-
 braces@^2.3.1, braces@^2.3.2:
   version "2.3.2"
   resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -2019,7 +2125,7 @@ camelcase@^4.1.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
   integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
 
-camelcase@^5.0.0:
+camelcase@^5.0.0, camelcase@^5.3.1:
   version "5.3.1"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@@ -2029,12 +2135,12 @@ caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001015:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0"
   integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==
 
-capture-exit@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
-  integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
+capture-exit@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
+  integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==
   dependencies:
-    rsvp "^3.3.3"
+    rsvp "^4.8.4"
 
 caseless@~0.12.0:
   version "0.12.0"
@@ -2060,17 +2166,6 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
-chalk@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
-  integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
-  dependencies:
-    ansi-styles "^2.2.1"
-    escape-string-regexp "^1.0.2"
-    has-ansi "^2.0.0"
-    strip-ansi "^3.0.0"
-    supports-color "^2.0.0"
-
 character-entities-html4@^1.0.0:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.3.tgz#5ce6e01618e47048ac22f34f7f39db5c6fd679ef"
@@ -2139,10 +2234,10 @@ chrome-trace-event@^1.0.2:
   dependencies:
     tslib "^1.9.0"
 
-ci-info@^1.5.0:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
-  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+ci-info@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+  integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
 
 cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   version "1.0.4"
@@ -2327,7 +2422,7 @@ content-type@^1.0.2:
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
-convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
+convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
   integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@@ -2369,11 +2464,6 @@ core-js@^2.4.0:
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
   integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
 
-core-js@^2.5.0:
-  version "2.6.11"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
-  integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
-
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2550,7 +2640,7 @@ debug@3.1.0:
   dependencies:
     ms "2.0.0"
 
-debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+debug@^2.2.0, debug@^2.3.3:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
   integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -2579,7 +2669,7 @@ decamelize-keys@^1.0.0:
     decamelize "^1.1.0"
     map-obj "^1.0.0"
 
-decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0:
+decamelize@^1.1.0, decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -2599,13 +2689,6 @@ deep-is@~0.1.3:
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 
-default-require-extensions@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
-  integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
-  dependencies:
-    strip-bom "^2.0.0"
-
 define-properties@^1.1.2, define-properties@^1.1.3, define-properties@~1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2686,10 +2769,10 @@ diff-match-patch@^1.0.4:
   resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
   integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
 
-diff@^3.2.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
-  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+diff-sequences@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
+  integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
 
 diff@^4.0.1:
   version "4.0.1"
@@ -2997,7 +3080,7 @@ errno@^0.1.3, errno@~0.1.7:
   dependencies:
     prr "~1.0.1"
 
-error-ex@^1.2.0, error-ex@^1.3.1:
+error-ex@^1.3.1:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
   integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
@@ -3093,7 +3176,7 @@ escape-html@^1.0.3:
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -3310,12 +3393,10 @@ except@^0.1.3:
   dependencies:
     indexof "0.0.1"
 
-exec-sh@^0.2.0:
-  version "0.2.2"
-  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
-  integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
-  dependencies:
-    merge "^1.2.0"
+exec-sh@^0.3.2:
+  version "0.3.4"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
+  integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==
 
 execa@^1.0.0:
   version "1.0.0"
@@ -3342,13 +3423,6 @@ exit@^0.1.2:
   resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
   integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
 
-expand-brackets@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
-  integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
-  dependencies:
-    is-posix-bracket "^0.1.0"
-
 expand-brackets@^2.1.4:
   version "2.1.4"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -3362,13 +3436,6 @@ expand-brackets@^2.1.4:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-expand-range@^1.8.1:
-  version "1.8.2"
-  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
-  integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
-  dependencies:
-    fill-range "^2.1.0"
-
 expand-tilde@^2.0.0, expand-tilde@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
@@ -3389,17 +3456,17 @@ expect@^1.20.2:
     object-keys "^1.0.9"
     tmatch "^2.0.1"
 
-expect@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
-  integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
+expect@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca"
+  integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==
   dependencies:
+    "@jest/types" "^24.9.0"
     ansi-styles "^3.2.0"
-    jest-diff "^23.6.0"
-    jest-get-type "^22.1.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
+    jest-get-type "^24.9.0"
+    jest-matcher-utils "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-regex-util "^24.9.0"
 
 extend-shallow@^2.0.1:
   version "2.0.1"
@@ -3430,13 +3497,6 @@ external-editor@^3.0.3:
     iconv-lite "^0.4.24"
     tmp "^0.0.33"
 
-extglob@^0.3.1:
-  version "0.3.2"
-  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
-  integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
-  dependencies:
-    is-extglob "^1.0.0"
-
 extglob@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@@ -3563,40 +3623,11 @@ file-saver@^1.3.3:
   resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8"
   integrity sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg==
 
-file-uri-to-path@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
-  integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
-
-filename-regex@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
-  integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
-fileset@^2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
-  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
-  dependencies:
-    glob "^7.0.3"
-    minimatch "^3.0.3"
-
 filesize@3.5.6:
   version "3.5.6"
   resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a"
   integrity sha1-X9mPPqyU7JUW747VeC+thKAaCho=
 
-fill-range@^2.1.0:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
-  integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
-  dependencies:
-    is-number "^2.1.0"
-    isobject "^2.0.0"
-    randomatic "^3.0.0"
-    repeat-element "^1.1.2"
-    repeat-string "^1.5.2"
-
 fill-range@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -3624,15 +3655,7 @@ find-up@4.1.0:
     locate-path "^5.0.0"
     path-exists "^4.0.0"
 
-find-up@^1.0.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
-  integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
-  dependencies:
-    path-exists "^2.0.0"
-    pinkie-promise "^2.0.0"
-
-find-up@^2.0.0, find-up@^2.1.0:
+find-up@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
   integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
@@ -3768,14 +3791,6 @@ fs.realpath@^1.0.0:
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
 
-fsevents@^1.2.3:
-  version "1.2.11"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3"
-  integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==
-  dependencies:
-    bindings "^1.5.0"
-    nan "^2.12.1"
-
 fsevents@^1.2.7:
   version "1.2.9"
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
@@ -3870,21 +3885,6 @@ gfm.css@^1.1.1:
   resolved "https://registry.yarnpkg.com/gfm.css/-/gfm.css-1.1.2.tgz#94acfa600672663b9dd0fd4b6ee5d11c8dbc161e"
   integrity sha512-KhK3rqxMj+UTLRxWnfUA5n8XZYMWfHrrcCxtWResYR2B3hWIqBM6v9FPGZSlVuX+ScLewizOvNkjYXuPs95ThQ==
 
-glob-base@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
-  integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
-  dependencies:
-    glob-parent "^2.0.0"
-    is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
-  integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
-  dependencies:
-    is-glob "^2.0.0"
-
 glob-parent@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@@ -3914,7 +3914,7 @@ glob@^5.0.14:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.1.6"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
   integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -3967,11 +3967,6 @@ globals@^11.1.0, globals@^11.7.0:
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
   integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
-globals@^9.18.0:
-  version "9.18.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
-  integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
-
 globby@^9.0.0:
   version "9.2.0"
   resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
@@ -4008,10 +4003,10 @@ growly@^1.3.0:
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
   integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
 
-handlebars@^4.0.3:
-  version "4.5.3"
-  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
-  integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
+handlebars@^4.1.2:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.6.0.tgz#33af6c3eda930d7a924f5d8f1c6d8edc3180512e"
+  integrity sha512-i1ZUP7Qp2JdkMaFon2a+b0m5geE8Z4ZTLaGkgrObkEd+OkUKyRbRWw4KxuFCoHfdETSY1yf9/574eVoNSiK7pw==
   dependencies:
     neo-async "^2.6.0"
     optimist "^0.6.1"
@@ -4032,18 +4027,6 @@ har-validator@~5.1.0:
     ajv "^6.5.5"
     har-schema "^2.0.0"
 
-has-ansi@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
-  integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
-  dependencies:
-    ansi-regex "^2.0.0"
-
-has-flag@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
-  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
-
 has-flag@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
@@ -4139,14 +4122,6 @@ hoist-non-react-statics@^3.3.0:
   dependencies:
     react-is "^16.7.0"
 
-home-or-tmp@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
-  integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.1"
-
 homedir-polyfill@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
@@ -4309,7 +4284,7 @@ import-lazy@^3.1.0:
   resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc"
   integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==
 
-import-local@2.0.0:
+import-local@2.0.0, import-local@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
   integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
@@ -4317,14 +4292,6 @@ import-local@2.0.0:
     pkg-dir "^3.0.0"
     resolve-cwd "^2.0.0"
 
-import-local@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
-  integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
-  dependencies:
-    pkg-dir "^2.0.0"
-    resolve-cwd "^2.0.0"
-
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -4515,12 +4482,12 @@ is-callable@^1.1.5:
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
   integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
 
-is-ci@^1.0.10:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
-  integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+is-ci@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+  integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
   dependencies:
-    ci-info "^1.5.0"
+    ci-info "^2.0.0"
 
 is-data-descriptor@^0.1.4:
   version "0.1.4"
@@ -4569,18 +4536,6 @@ is-directory@^0.3.1:
   resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
   integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
 
-is-dotfile@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
-  integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
-  integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
-  dependencies:
-    is-primitive "^2.0.0"
-
 is-equal@^1.5.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/is-equal/-/is-equal-1.6.1.tgz#74fafde5060fcaf187041c05f11f0b9f020bb9b3"
@@ -4617,11 +4572,6 @@ is-extendable@^1.0.1:
   dependencies:
     is-plain-object "^2.0.4"
 
-is-extglob@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
-  integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
 is-extglob@^2.1.0, is-extglob@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -4644,23 +4594,16 @@ is-fullwidth-code-point@^3.0.0:
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
   integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
 
-is-generator-fn@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
-  integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
+is-generator-fn@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+  integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
 
 is-generator-function@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
   integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==
 
-is-glob@^2.0.0, is-glob@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
-  integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
-  dependencies:
-    is-extglob "^1.0.0"
-
 is-glob@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
@@ -4702,13 +4645,6 @@ is-number-object@^1.0.4:
   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
   integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
 
-is-number@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
-  integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
-  dependencies:
-    kind-of "^3.0.2"
-
 is-number@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -4716,11 +4652,6 @@ is-number@^3.0.0:
   dependencies:
     kind-of "^3.0.2"
 
-is-number@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
-  integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
 is-obj@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@@ -4738,16 +4669,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
-is-posix-bracket@^0.1.0:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
-  integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
-  integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
 is-promise@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
@@ -4814,11 +4735,6 @@ is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
-is-utf8@^0.2.0:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
-  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
 is-weakmap@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.0.tgz#88bd0b8ec3a5724477637d58ed96cb00552593fd"
@@ -4889,386 +4805,390 @@ isstream@~0.1.2:
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
-istanbul-api@^1.3.1:
-  version "1.3.7"
-  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
-  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
-  dependencies:
-    async "^2.1.4"
-    fileset "^2.0.2"
-    istanbul-lib-coverage "^1.2.1"
-    istanbul-lib-hook "^1.2.2"
-    istanbul-lib-instrument "^1.10.2"
-    istanbul-lib-report "^1.1.5"
-    istanbul-lib-source-maps "^1.2.6"
-    istanbul-reports "^1.5.1"
-    js-yaml "^3.7.0"
-    mkdirp "^0.5.1"
-    once "^1.4.0"
+istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
+  integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
 
-istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
-  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
-
-istanbul-lib-hook@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
-  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
+  integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
   dependencies:
-    append-transform "^0.4.0"
+    "@babel/generator" "^7.4.0"
+    "@babel/parser" "^7.4.3"
+    "@babel/template" "^7.4.0"
+    "@babel/traverse" "^7.4.3"
+    "@babel/types" "^7.4.0"
+    istanbul-lib-coverage "^2.0.5"
+    semver "^6.0.0"
 
-istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
-  version "1.10.2"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
-  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+istanbul-lib-report@^2.0.4:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
+  integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
   dependencies:
-    babel-generator "^6.18.0"
-    babel-template "^6.16.0"
-    babel-traverse "^6.18.0"
-    babel-types "^6.18.0"
-    babylon "^6.18.0"
-    istanbul-lib-coverage "^1.2.1"
-    semver "^5.3.0"
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    supports-color "^6.1.0"
 
-istanbul-lib-report@^1.1.5:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
-  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+istanbul-lib-source-maps@^3.0.1:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
+  integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
   dependencies:
-    istanbul-lib-coverage "^1.2.1"
-    mkdirp "^0.5.1"
-    path-parse "^1.0.5"
-    supports-color "^3.1.2"
+    debug "^4.1.1"
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    rimraf "^2.6.3"
+    source-map "^0.6.1"
 
-istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
-  version "1.2.6"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
-  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+istanbul-reports@^2.2.6:
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
+  integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
   dependencies:
-    debug "^3.1.0"
-    istanbul-lib-coverage "^1.2.1"
-    mkdirp "^0.5.1"
-    rimraf "^2.6.1"
-    source-map "^0.5.3"
+    handlebars "^4.1.2"
 
-istanbul-reports@^1.5.1:
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
-  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
-  dependencies:
-    handlebars "^4.0.3"
-
-jest-changed-files@^23.4.2:
-  version "23.4.2"
-  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
-  integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+jest-changed-files@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039"
+  integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==
   dependencies:
+    "@jest/types" "^24.9.0"
+    execa "^1.0.0"
     throat "^4.0.0"
 
-jest-cli@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
-  integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+jest-cli@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af"
+  integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==
   dependencies:
-    ansi-escapes "^3.0.0"
+    "@jest/core" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
     chalk "^2.0.1"
     exit "^0.1.2"
-    glob "^7.1.2"
-    graceful-fs "^4.1.11"
-    import-local "^1.0.0"
-    is-ci "^1.0.10"
-    istanbul-api "^1.3.1"
-    istanbul-lib-coverage "^1.2.0"
-    istanbul-lib-instrument "^1.10.1"
-    istanbul-lib-source-maps "^1.2.4"
-    jest-changed-files "^23.4.2"
-    jest-config "^23.6.0"
-    jest-environment-jsdom "^23.4.0"
-    jest-get-type "^22.1.0"
-    jest-haste-map "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve-dependencies "^23.6.0"
-    jest-runner "^23.6.0"
-    jest-runtime "^23.6.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    jest-watcher "^23.4.0"
-    jest-worker "^23.2.0"
-    micromatch "^2.3.11"
-    node-notifier "^5.2.1"
-    prompts "^0.1.9"
-    realpath-native "^1.0.0"
-    rimraf "^2.5.4"
-    slash "^1.0.0"
-    string-length "^2.0.0"
-    strip-ansi "^4.0.0"
-    which "^1.2.12"
-    yargs "^11.0.0"
+    import-local "^2.0.0"
+    is-ci "^2.0.0"
+    jest-config "^24.9.0"
+    jest-util "^24.9.0"
+    jest-validate "^24.9.0"
+    prompts "^2.0.1"
+    realpath-native "^1.1.0"
+    yargs "^13.3.0"
 
-jest-config@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
-  integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+jest-config@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5"
+  integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==
   dependencies:
-    babel-core "^6.0.0"
-    babel-jest "^23.6.0"
+    "@babel/core" "^7.1.0"
+    "@jest/test-sequencer" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    babel-jest "^24.9.0"
     chalk "^2.0.1"
     glob "^7.1.1"
-    jest-environment-jsdom "^23.4.0"
-    jest-environment-node "^23.4.0"
-    jest-get-type "^22.1.0"
-    jest-jasmine2 "^23.6.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    micromatch "^2.3.11"
-    pretty-format "^23.6.0"
+    jest-environment-jsdom "^24.9.0"
+    jest-environment-node "^24.9.0"
+    jest-get-type "^24.9.0"
+    jest-jasmine2 "^24.9.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve "^24.9.0"
+    jest-util "^24.9.0"
+    jest-validate "^24.9.0"
+    micromatch "^3.1.10"
+    pretty-format "^24.9.0"
+    realpath-native "^1.1.0"
 
-jest-diff@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
-  integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
+jest-diff@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
+  integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
   dependencies:
     chalk "^2.0.1"
-    diff "^3.2.0"
-    jest-get-type "^22.1.0"
-    pretty-format "^23.6.0"
+    diff-sequences "^24.9.0"
+    jest-get-type "^24.9.0"
+    pretty-format "^24.9.0"
 
-jest-docblock@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
-  integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
+jest-docblock@^24.3.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2"
+  integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==
   dependencies:
     detect-newline "^2.1.0"
 
-jest-each@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
-  integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+jest-each@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05"
+  integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==
   dependencies:
+    "@jest/types" "^24.9.0"
     chalk "^2.0.1"
-    pretty-format "^23.6.0"
+    jest-get-type "^24.9.0"
+    jest-util "^24.9.0"
+    pretty-format "^24.9.0"
 
-jest-environment-jsdom@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
-  integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
+jest-environment-jsdom@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b"
+  integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==
   dependencies:
-    jest-mock "^23.2.0"
-    jest-util "^23.4.0"
+    "@jest/environment" "^24.9.0"
+    "@jest/fake-timers" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    jest-mock "^24.9.0"
+    jest-util "^24.9.0"
     jsdom "^11.5.1"
 
-jest-environment-node@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
-  integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
+jest-environment-node@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3"
+  integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==
   dependencies:
-    jest-mock "^23.2.0"
-    jest-util "^23.4.0"
+    "@jest/environment" "^24.9.0"
+    "@jest/fake-timers" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    jest-mock "^24.9.0"
+    jest-util "^24.9.0"
 
-jest-get-type@^22.1.0:
-  version "22.4.3"
-  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
-  integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+jest-get-type@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
+  integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
 
-jest-haste-map@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
-  integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+jest-haste-map@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d"
+  integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==
   dependencies:
+    "@jest/types" "^24.9.0"
+    anymatch "^2.0.0"
     fb-watchman "^2.0.0"
-    graceful-fs "^4.1.11"
+    graceful-fs "^4.1.15"
     invariant "^2.2.4"
-    jest-docblock "^23.2.0"
-    jest-serializer "^23.0.1"
-    jest-worker "^23.2.0"
-    micromatch "^2.3.11"
-    sane "^2.0.0"
+    jest-serializer "^24.9.0"
+    jest-util "^24.9.0"
+    jest-worker "^24.9.0"
+    micromatch "^3.1.10"
+    sane "^4.0.3"
+    walker "^1.0.7"
+  optionalDependencies:
+    fsevents "^1.2.7"
 
-jest-jasmine2@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
-  integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
+jest-jasmine2@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0"
+  integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==
   dependencies:
-    babel-traverse "^6.0.0"
+    "@babel/traverse" "^7.1.0"
+    "@jest/environment" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
     chalk "^2.0.1"
     co "^4.6.0"
-    expect "^23.6.0"
-    is-generator-fn "^1.0.0"
-    jest-diff "^23.6.0"
-    jest-each "^23.6.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    pretty-format "^23.6.0"
+    expect "^24.9.0"
+    is-generator-fn "^2.0.0"
+    jest-each "^24.9.0"
+    jest-matcher-utils "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-runtime "^24.9.0"
+    jest-snapshot "^24.9.0"
+    jest-util "^24.9.0"
+    pretty-format "^24.9.0"
+    throat "^4.0.0"
 
-jest-leak-detector@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
-  integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+jest-leak-detector@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a"
+  integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==
   dependencies:
-    pretty-format "^23.6.0"
+    jest-get-type "^24.9.0"
+    pretty-format "^24.9.0"
 
-jest-matcher-utils@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
-  integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+jest-matcher-utils@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073"
+  integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==
   dependencies:
     chalk "^2.0.1"
-    jest-get-type "^22.1.0"
-    pretty-format "^23.6.0"
+    jest-diff "^24.9.0"
+    jest-get-type "^24.9.0"
+    pretty-format "^24.9.0"
 
-jest-message-util@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
-  integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
+jest-message-util@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3"
+  integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==
   dependencies:
-    "@babel/code-frame" "^7.0.0-beta.35"
+    "@babel/code-frame" "^7.0.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    "@types/stack-utils" "^1.0.1"
     chalk "^2.0.1"
-    micromatch "^2.3.11"
-    slash "^1.0.0"
+    micromatch "^3.1.10"
+    slash "^2.0.0"
     stack-utils "^1.0.1"
 
-jest-mock@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
-  integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
-
-jest-regex-util@^23.3.0:
-  version "23.3.0"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
-  integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
-
-jest-resolve-dependencies@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
-  integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+jest-mock@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6"
+  integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==
   dependencies:
-    jest-regex-util "^23.3.0"
-    jest-snapshot "^23.6.0"
+    "@jest/types" "^24.9.0"
 
-jest-resolve@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
-  integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+jest-pnp-resolver@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a"
+  integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==
+
+jest-regex-util@^24.3.0, jest-regex-util@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636"
+  integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==
+
+jest-resolve-dependencies@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab"
+  integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==
   dependencies:
+    "@jest/types" "^24.9.0"
+    jest-regex-util "^24.3.0"
+    jest-snapshot "^24.9.0"
+
+jest-resolve@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321"
+  integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==
+  dependencies:
+    "@jest/types" "^24.9.0"
     browser-resolve "^1.11.3"
     chalk "^2.0.1"
-    realpath-native "^1.0.0"
+    jest-pnp-resolver "^1.2.1"
+    realpath-native "^1.1.0"
 
-jest-runner@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
-  integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+jest-runner@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42"
+  integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==
   dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/environment" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    chalk "^2.4.2"
     exit "^0.1.2"
-    graceful-fs "^4.1.11"
-    jest-config "^23.6.0"
-    jest-docblock "^23.2.0"
-    jest-haste-map "^23.6.0"
-    jest-jasmine2 "^23.6.0"
-    jest-leak-detector "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-runtime "^23.6.0"
-    jest-util "^23.4.0"
-    jest-worker "^23.2.0"
+    graceful-fs "^4.1.15"
+    jest-config "^24.9.0"
+    jest-docblock "^24.3.0"
+    jest-haste-map "^24.9.0"
+    jest-jasmine2 "^24.9.0"
+    jest-leak-detector "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-resolve "^24.9.0"
+    jest-runtime "^24.9.0"
+    jest-util "^24.9.0"
+    jest-worker "^24.6.0"
     source-map-support "^0.5.6"
     throat "^4.0.0"
 
-jest-runtime@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
-  integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+jest-runtime@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac"
+  integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==
   dependencies:
-    babel-core "^6.0.0"
-    babel-plugin-istanbul "^4.1.6"
+    "@jest/console" "^24.7.1"
+    "@jest/environment" "^24.9.0"
+    "@jest/source-map" "^24.3.0"
+    "@jest/transform" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    "@types/yargs" "^13.0.0"
     chalk "^2.0.1"
-    convert-source-map "^1.4.0"
     exit "^0.1.2"
-    fast-json-stable-stringify "^2.0.0"
-    graceful-fs "^4.1.11"
-    jest-config "^23.6.0"
-    jest-haste-map "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve "^23.6.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    micromatch "^2.3.11"
-    realpath-native "^1.0.0"
-    slash "^1.0.0"
-    strip-bom "3.0.0"
-    write-file-atomic "^2.1.0"
-    yargs "^11.0.0"
+    glob "^7.1.3"
+    graceful-fs "^4.1.15"
+    jest-config "^24.9.0"
+    jest-haste-map "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-mock "^24.9.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve "^24.9.0"
+    jest-snapshot "^24.9.0"
+    jest-util "^24.9.0"
+    jest-validate "^24.9.0"
+    realpath-native "^1.1.0"
+    slash "^2.0.0"
+    strip-bom "^3.0.0"
+    yargs "^13.3.0"
 
-jest-serializer@^23.0.1:
-  version "23.0.1"
-  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
-  integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
+jest-serializer@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73"
+  integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==
 
-jest-snapshot@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
-  integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
+jest-snapshot@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba"
+  integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==
   dependencies:
-    babel-types "^6.0.0"
+    "@babel/types" "^7.0.0"
+    "@jest/types" "^24.9.0"
     chalk "^2.0.1"
-    jest-diff "^23.6.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-resolve "^23.6.0"
+    expect "^24.9.0"
+    jest-diff "^24.9.0"
+    jest-get-type "^24.9.0"
+    jest-matcher-utils "^24.9.0"
+    jest-message-util "^24.9.0"
+    jest-resolve "^24.9.0"
     mkdirp "^0.5.1"
     natural-compare "^1.4.0"
-    pretty-format "^23.6.0"
-    semver "^5.5.0"
+    pretty-format "^24.9.0"
+    semver "^6.2.0"
 
-jest-util@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
-  integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
+jest-util@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162"
+  integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==
   dependencies:
-    callsites "^2.0.0"
+    "@jest/console" "^24.9.0"
+    "@jest/fake-timers" "^24.9.0"
+    "@jest/source-map" "^24.9.0"
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    callsites "^3.0.0"
     chalk "^2.0.1"
-    graceful-fs "^4.1.11"
-    is-ci "^1.0.10"
-    jest-message-util "^23.4.0"
+    graceful-fs "^4.1.15"
+    is-ci "^2.0.0"
     mkdirp "^0.5.1"
-    slash "^1.0.0"
+    slash "^2.0.0"
     source-map "^0.6.0"
 
-jest-validate@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
-  integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+jest-validate@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab"
+  integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==
   dependencies:
+    "@jest/types" "^24.9.0"
+    camelcase "^5.3.1"
     chalk "^2.0.1"
-    jest-get-type "^22.1.0"
-    leven "^2.1.0"
-    pretty-format "^23.6.0"
+    jest-get-type "^24.9.0"
+    leven "^3.1.0"
+    pretty-format "^24.9.0"
 
-jest-watcher@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
-  integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
+jest-watcher@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b"
+  integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==
   dependencies:
+    "@jest/test-result" "^24.9.0"
+    "@jest/types" "^24.9.0"
+    "@types/yargs" "^13.0.0"
     ansi-escapes "^3.0.0"
     chalk "^2.0.1"
+    jest-util "^24.9.0"
     string-length "^2.0.0"
 
-jest-worker@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
-  integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
-  dependencies:
-    merge-stream "^1.0.1"
-
-jest-worker@^24.6.0:
+jest-worker@^24.6.0, jest-worker@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
   integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==
@@ -5276,13 +5196,13 @@ jest-worker@^24.6.0:
     merge-stream "^2.0.0"
     supports-color "^6.1.0"
 
-jest@^23.2.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
-  integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+jest@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171"
+  integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==
   dependencies:
-    import-local "^1.0.0"
-    jest-cli "^23.6.0"
+    import-local "^2.0.0"
+    jest-cli "^24.9.0"
 
 jquery@^3.3.1:
   version "3.4.1"
@@ -5299,12 +5219,7 @@ js-levenshtein@^1.1.3:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
   integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
 
-js-tokens@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
-  integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-
-js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.7.0:
+js-yaml@^3.13.0, js-yaml@^3.13.1:
   version "3.13.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
   integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@@ -5388,11 +5303,6 @@ json-stringify-safe@~5.0.1:
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
   integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
 
-json5@^0.5.1:
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
-  integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
-
 json5@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
@@ -5449,10 +5359,10 @@ kind-of@^6.0.0, kind-of@^6.0.2:
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
   integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
 
-kleur@^2.0.1:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
-  integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+kleur@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+  integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
 
 known-css-properties@^0.11.0:
   version "0.11.0"
@@ -5476,6 +5386,11 @@ leven@^2.1.0:
   resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
   integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
 
+leven@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+  integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
 levn@^0.3.0, levn@~0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
@@ -5493,17 +5408,6 @@ linkifyjs@^2.1.6:
     react "^16.4.2"
     react-dom "^16.4.2"
 
-load-json-file@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
-  integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
-  dependencies:
-    graceful-fs "^4.1.2"
-    parse-json "^2.2.0"
-    pify "^2.0.0"
-    pinkie-promise "^2.0.0"
-    strip-bom "^2.0.0"
-
 load-json-file@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
@@ -5741,11 +5645,6 @@ markdown-table@^1.1.0:
   resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60"
   integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
 
-math-random@^1.0.1:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
-  integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
-
 mathml-tag-names@^2.0.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc"
@@ -5843,13 +5742,6 @@ meow@^5.0.0:
     trim-newlines "^2.0.0"
     yargs-parser "^10.0.0"
 
-merge-stream@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
-  integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
-  dependencies:
-    readable-stream "^2.0.1"
-
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -5860,30 +5752,6 @@ merge2@^1.2.3:
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
   integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
 
-merge@^1.2.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
-  integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
-
-micromatch@^2.3.11:
-  version "2.3.11"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
-  integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
-  dependencies:
-    arr-diff "^2.0.0"
-    array-unique "^0.2.1"
-    braces "^1.8.2"
-    expand-brackets "^0.1.4"
-    extglob "^0.3.1"
-    filename-regex "^2.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.1"
-    kind-of "^3.0.2"
-    normalize-path "^2.0.1"
-    object.omit "^2.0.0"
-    parse-glob "^3.0.4"
-    regex-cache "^0.4.2"
-
 micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
@@ -5943,7 +5811,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
 
-"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -6179,7 +6047,7 @@ node-modules-regexp@^1.0.0:
   resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
   integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
 
-node-notifier@^5.2.1:
+node-notifier@^5.4.2:
   version "5.4.3"
   resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50"
   integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==
@@ -6231,7 +6099,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
     semver "2 || 3 || 4 || 5"
     validate-npm-package-license "^3.0.1"
 
-normalize-path@^2.0.1, normalize-path@^2.1.1:
+normalize-path@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
   integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
@@ -6404,14 +6272,6 @@ object.getownpropertydescriptors@^2.0.3:
     define-properties "^1.1.3"
     es-abstract "^1.17.0-next.1"
 
-object.omit@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
-  integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
-  dependencies:
-    for-own "^0.1.4"
-    is-extendable "^0.1.1"
-
 object.pick@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@@ -6492,7 +6352,7 @@ os-locale@^3.0.0, os-locale@^3.1.0:
     lcid "^2.0.0"
     mem "^4.0.0"
 
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
@@ -6510,6 +6370,13 @@ p-defer@^1.0.0:
   resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
   integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
 
+p-each-series@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
+  integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=
+  dependencies:
+    p-reduce "^1.0.0"
+
 p-finally@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -6555,6 +6422,11 @@ p-locate@^4.1.0:
   dependencies:
     p-limit "^2.2.0"
 
+p-reduce@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
+  integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
+
 p-try@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
@@ -6610,23 +6482,6 @@ parse-entities@^1.0.2, parse-entities@^1.1.0:
     is-decimal "^1.0.0"
     is-hexadecimal "^1.0.0"
 
-parse-glob@^3.0.4:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
-  integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
-  dependencies:
-    glob-base "^0.3.0"
-    is-dotfile "^1.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.0"
-
-parse-json@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
-  integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
-  dependencies:
-    error-ex "^1.2.0"
-
 parse-json@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -6667,13 +6522,6 @@ path-dirname@^1.0.0:
   resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
   integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
 
-path-exists@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
-  integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
-  dependencies:
-    pinkie-promise "^2.0.0"
-
 path-exists@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -6684,7 +6532,7 @@ path-exists@^4.0.0:
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
   integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
 
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
   integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
@@ -6699,20 +6547,11 @@ path-key@^2.0.0, path-key@^2.0.1:
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
   integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 
-path-parse@^1.0.5, path-parse@^1.0.6:
+path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
 
-path-type@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
-  integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
-  dependencies:
-    graceful-fs "^4.1.2"
-    pify "^2.0.0"
-    pinkie-promise "^2.0.0"
-
 path-type@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@@ -6741,11 +6580,6 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-pify@^2.0.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
-  integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
 pify@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
@@ -6756,32 +6590,13 @@ pify@^4.0.0, pify@^4.0.1:
   resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
-pinkie-promise@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
-  integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
-  dependencies:
-    pinkie "^2.0.0"
-
-pinkie@^2.0.0:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
-  integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
-pirates@^4.0.0:
+pirates@^4.0.0, pirates@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
   integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
   dependencies:
     node-modules-regexp "^1.0.0"
 
-pkg-dir@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
-  integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
-  dependencies:
-    find-up "^2.1.0"
-
 pkg-dir@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@@ -6936,20 +6751,17 @@ prelude-ls@~1.1.2:
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
   integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 
-preserve@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-  integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
-pretty-format@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
-  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+pretty-format@^24.9.0:
+  version "24.9.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
+  integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==
   dependencies:
-    ansi-regex "^3.0.0"
+    "@jest/types" "^24.9.0"
+    ansi-regex "^4.0.0"
     ansi-styles "^3.2.0"
+    react-is "^16.8.4"
 
-private@^0.1.6, private@^0.1.8:
+private@^0.1.6:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
   integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
@@ -6989,13 +6801,13 @@ promise@^7.0.3, promise@^7.1.1:
   dependencies:
     asap "~2.0.3"
 
-prompts@^0.1.9:
-  version "0.1.14"
-  resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
-  integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+prompts@^2.0.1:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4"
+  integrity sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==
   dependencies:
-    kleur "^2.0.1"
-    sisteransi "^0.1.1"
+    kleur "^3.0.3"
+    sisteransi "^1.0.3"
 
 prop-types-exact@^1.2.0:
   version "1.2.0"
@@ -7144,15 +6956,6 @@ randexp@0.4.6:
     discontinuous-range "1.0.0"
     ret "~0.1.10"
 
-randomatic@^3.0.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
-  integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
-  dependencies:
-    is-number "^4.0.0"
-    kind-of "^6.0.0"
-    math-random "^1.0.1"
-
 randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -7236,7 +7039,7 @@ react-focus-lock@^2.2.1:
   dependencies:
     gemini-scrollbar matrix-org/gemini-scrollbar#91e1e566
 
-react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0:
+react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
   version "16.12.0"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
   integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
@@ -7298,14 +7101,6 @@ react@^16.4.2, react@^16.9.0:
     object-assign "^4.1.1"
     prop-types "^15.6.2"
 
-read-pkg-up@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
-  integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
-  dependencies:
-    find-up "^1.0.0"
-    read-pkg "^1.0.0"
-
 read-pkg-up@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
@@ -7314,14 +7109,13 @@ read-pkg-up@^3.0.0:
     find-up "^2.0.0"
     read-pkg "^3.0.0"
 
-read-pkg@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
-  integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+read-pkg-up@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
+  integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==
   dependencies:
-    load-json-file "^1.0.0"
-    normalize-package-data "^2.3.2"
-    path-type "^1.0.0"
+    find-up "^3.0.0"
+    read-pkg "^3.0.0"
 
 read-pkg@^3.0.0:
   version "3.0.0"
@@ -7372,7 +7166,7 @@ readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
-realpath-native@^1.0.0:
+realpath-native@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
   integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
@@ -7436,13 +7230,6 @@ regenerator-transform@^0.14.0:
   dependencies:
     private "^0.1.6"
 
-regex-cache@^0.4.2:
-  version "0.4.4"
-  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
-  integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
-  dependencies:
-    is-equal-shallow "^0.1.3"
-
 regex-not@^1.0.0, regex-not@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@@ -7548,7 +7335,7 @@ repeat-element@^1.1.2:
   resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
   integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
 
-repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1:
+repeat-string@^1.5.4, repeat-string@^1.6.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
   integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
@@ -7745,10 +7532,10 @@ rst-selector-parser@^2.2.3:
     lodash.flattendeep "^4.4.0"
     nearley "^2.7.10"
 
-rsvp@^3.3.3:
-  version "3.6.2"
-  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
-  integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+rsvp@^4.8.4:
+  version "4.8.5"
+  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
+  integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
 
 run-async@^2.2.0:
   version "2.3.0"
@@ -7793,21 +7580,20 @@ safe-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-sane@^2.0.0:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
-  integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
+sane@^4.0.3:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded"
+  integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==
   dependencies:
+    "@cnakazawa/watch" "^1.0.3"
     anymatch "^2.0.0"
-    capture-exit "^1.2.0"
-    exec-sh "^0.2.0"
+    capture-exit "^2.0.0"
+    exec-sh "^0.3.2"
+    execa "^1.0.0"
     fb-watchman "^2.0.0"
     micromatch "^3.1.4"
     minimist "^1.1.1"
     walker "~1.0.5"
-    watch "~0.18.0"
-  optionalDependencies:
-    fsevents "^1.2.3"
 
 sanitize-html@^1.18.4:
   version "1.20.1"
@@ -7852,7 +7638,7 @@ schema-utils@^1.0.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
 
-semver@6.3.0, semver@^6.3.0:
+semver@6.3.0, semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -7912,21 +7698,16 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
-sisteransi@^0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
-  integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
+sisteransi@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3"
+  integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==
 
 sjcl@^1.0.3:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
   integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
 
-slash@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
-  integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
-
 slash@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
@@ -8016,13 +7797,6 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.4.15:
-  version "0.4.18"
-  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
-  integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
-  dependencies:
-    source-map "^0.5.6"
-
 source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12:
   version "0.5.16"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
@@ -8036,7 +7810,7 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
-source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -8318,18 +8092,11 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
-strip-bom@3.0.0, strip-bom@^3.0.0:
+strip-bom@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
   integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
 
-strip-bom@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
-  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
-  dependencies:
-    is-utf8 "^0.2.0"
-
 strip-eof@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -8454,18 +8221,6 @@ supports-color@6.1.0, supports-color@^6.1.0:
   dependencies:
     has-flag "^3.0.0"
 
-supports-color@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
-  integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^3.1.2:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
-  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
-  dependencies:
-    has-flag "^1.0.0"
-
 supports-color@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
@@ -8547,16 +8302,15 @@ terser@^4.1.0, terser@^4.1.2:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
-test-exclude@^4.2.1:
-  version "4.2.3"
-  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
-  integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+test-exclude@^5.2.3:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0"
+  integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==
   dependencies:
-    arrify "^1.0.1"
-    micromatch "^2.3.11"
-    object-assign "^4.1.0"
-    read-pkg-up "^1.0.1"
-    require-main-filename "^1.0.1"
+    glob "^7.1.3"
+    minimatch "^3.0.4"
+    read-pkg-up "^4.0.0"
+    require-main-filename "^2.0.0"
 
 text-encoding-utf-8@^1.0.1:
   version "1.0.2"
@@ -8615,11 +8369,6 @@ to-arraybuffer@^1.0.0:
   resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
   integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
 
-to-fast-properties@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-  integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
-
 to-fast-properties@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -9082,7 +8831,7 @@ walk@^2.3.9:
   dependencies:
     foreachasync "^3.0.0"
 
-walker@~1.0.5:
+walker@^1.0.7, walker@~1.0.5:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
   integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
@@ -9096,14 +8845,6 @@ warning@^3.0.0:
   dependencies:
     loose-envify "^1.0.0"
 
-watch@~0.18.0:
-  version "0.18.0"
-  resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
-  integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
-  dependencies:
-    exec-sh "^0.2.0"
-    minimist "^1.2.0"
-
 watchpack@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
@@ -9248,7 +8989,7 @@ which-module@^2.0.0:
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -9301,10 +9042,10 @@ wrappy@1:
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 
-write-file-atomic@^2.1.0:
-  version "2.4.3"
-  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
-  integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+write-file-atomic@2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529"
+  integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==
   dependencies:
     graceful-fs "^4.1.11"
     imurmurhash "^0.1.4"
@@ -9339,11 +9080,6 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
   integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
 
-y18n@^3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
-  integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
-
 "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@@ -9369,7 +9105,7 @@ yargs-parser@^11.1.1:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
-yargs-parser@^13.1.0:
+yargs-parser@^13.1.0, yargs-parser@^13.1.1:
   version "13.1.1"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
   integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
@@ -9377,13 +9113,6 @@ yargs-parser@^13.1.0:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
-yargs-parser@^9.0.2:
-  version "9.0.2"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
-  integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
-  dependencies:
-    camelcase "^4.1.0"
-
 yargs@13.2.4:
   version "13.2.4"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
@@ -9401,24 +9130,6 @@ yargs@13.2.4:
     y18n "^4.0.0"
     yargs-parser "^13.1.0"
 
-yargs@^11.0.0:
-  version "11.1.1"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
-  integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
-  dependencies:
-    cliui "^4.0.0"
-    decamelize "^1.1.1"
-    find-up "^2.1.0"
-    get-caller-file "^1.0.1"
-    os-locale "^3.1.0"
-    require-directory "^2.1.1"
-    require-main-filename "^1.0.1"
-    set-blocking "^2.0.0"
-    string-width "^2.0.0"
-    which-module "^2.0.0"
-    y18n "^3.2.1"
-    yargs-parser "^9.0.2"
-
 yargs@^12.0.5:
   version "12.0.5"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
@@ -9437,6 +9148,22 @@ yargs@^12.0.5:
     y18n "^3.2.1 || ^4.0.0"
     yargs-parser "^11.1.1"
 
+yargs@^13.3.0:
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83"
+  integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==
+  dependencies:
+    cliui "^5.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^13.1.1"
+
 zxcvbn@^4.4.2:
   version "4.4.2"
   resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"

From 5f514329872cabd3d00cfca7640acca227c3f962 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:14:50 -0700
Subject: [PATCH 60/86] Convert babel config to a different babel config

This is needed because of https://github.com/facebook/jest/issues/6229
---
 .babelrc => babel.config.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
 rename .babelrc => babel.config.js (97%)

diff --git a/.babelrc b/babel.config.js
similarity index 97%
rename from .babelrc
rename to babel.config.js
index f75a9f82ef..c83be72518 100644
--- a/.babelrc
+++ b/babel.config.js
@@ -1,4 +1,4 @@
-{
+module.exports = {
     "sourceMaps": "inline",
     "presets": [
         ["@babel/preset-env", {
@@ -23,4 +23,4 @@
         "@babel/plugin-syntax-dynamic-import",
         "@babel/plugin-transform-runtime"
     ]
-}
+};

From 0e8af15b9c944a6ea83c4c887055ec6ae36edfe2 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:15:13 -0700
Subject: [PATCH 61/86] Add webcrypto dep back

Probably accidentally merge-conflicted out
---
 package.json |  1 +
 yarn.lock    | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 29567928f5..d6cb56b136 100644
--- a/package.json
+++ b/package.json
@@ -121,6 +121,7 @@
     "@babel/preset-typescript": "^7.7.4",
     "@babel/register": "^7.7.4",
     "@babel/runtime": "^7.7.6",
+    "@peculiar/webcrypto": "^1.0.22",
     "babel-eslint": "^10.0.3",
     "babel-jest": "^24.9.0",
     "chokidar": "^2.1.2",
diff --git a/yarn.lock b/yarn.lock
index 49c559a612..e7998243eb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1110,6 +1110,33 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
+"@peculiar/asn1-schema@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-1.0.3.tgz#e55ff9e98a1cf31832629aabacf85be3edf13a48"
+  integrity sha512-Tfgj9eNJ6cTKEtEuidKenLHMx/Q5M8KEE9hnohHqvdpqHJXWYr5RlT3GjAHPjGXy5+mr7sSfuXfzE6aAkEGN7A==
+  dependencies:
+    asn1js "^2.0.22"
+    tslib "^1.9.3"
+
+"@peculiar/json-schema@^1.1.6":
+  version "1.1.9"
+  resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.9.tgz#b746e046b787607a1b2804f64437fda2527b3e62"
+  integrity sha512-F2ST2y/IQPgY+1QMw1Q33sqJbGDCeO3lGqI69SL3Hgo0++7iHqprUB1QyxB/A7bN3tuM65MBxoM2JLbwh42lsQ==
+  dependencies:
+    tslib "^1.10.0"
+
+"@peculiar/webcrypto@^1.0.22":
+  version "1.0.22"
+  resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.0.22.tgz#9dae652fce6bacd9df15bc91965797cee33adf67"
+  integrity sha512-NP6H6ZGXUvJnQJCWzUgnRcQv+9nMCNwLUDhTwOxRUwPFvtHauMOl0oPTKUjbhInCMaE55gJqB4yc0YKbde6Exw==
+  dependencies:
+    "@peculiar/asn1-schema" "^1.0.3"
+    "@peculiar/json-schema" "^1.1.6"
+    asn1js "^2.0.26"
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
+    webcrypto-core "^1.0.17"
+
 "@types/babel__core@^7.1.0":
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
@@ -1660,6 +1687,13 @@ asn1@~0.2.3:
   dependencies:
     safer-buffer "~2.1.0"
 
+asn1js@^2.0.22, asn1js@^2.0.26:
+  version "2.0.26"
+  resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-2.0.26.tgz#0a6d435000f556a96c6012969d9704d981b71251"
+  integrity sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==
+  dependencies:
+    pvutils latest
+
 assert-plus@1.0.0, assert-plus@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
@@ -6894,6 +6928,18 @@ punycode@^2.1.0, punycode@^2.1.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
+pvtsutils@^1.0.9:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.0.9.tgz#0eb6106f27878ccaa55e7dfbf6bd2c75af461dee"
+  integrity sha512-/kDsuCKPqJuIzn37w6+iN+TiSrN+zrwPEd7FjT61oNbRvceGdsS94fMEWZ4/h6QZU5EZhBMiV+79IYedroP/Yw==
+  dependencies:
+    tslib "^1.10.0"
+
+pvutils@latest:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
+  integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
+
 qr.js@0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
@@ -8447,7 +8493,7 @@ trough@^1.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e"
   integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==
 
-tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
   integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
@@ -8854,6 +8900,14 @@ watchpack@^1.6.0:
     graceful-fs "^4.1.2"
     neo-async "^2.5.0"
 
+webcrypto-core@^1.0.17:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.0.17.tgz#a9354bc0b1ba6735e882f4137ede2c4366e6ad9b"
+  integrity sha512-7jxTLgtM+TahBPErx/Dd2XvxFDfWJrHxjVeTSvIa4LSgiYrmCPlC2INiAMAfb8MbtHiwJKKqF5sPS0AWNjBbXw==
+  dependencies:
+    pvtsutils "^1.0.9"
+    tslib "^1.10.0"
+
 webidl-conversions@^4.0.2:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"

From ffd037dfa8e390a1a18e47aebcab4b1e17f1da19 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:22:21 -0700
Subject: [PATCH 62/86] Fix resolution of files for Jest

---
 __mocks__/languages.json | 10 ++++++++++
 package.json             |  8 ++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)
 create mode 100644 __mocks__/languages.json

diff --git a/__mocks__/languages.json b/__mocks__/languages.json
new file mode 100644
index 0000000000..f62fe9b9b4
--- /dev/null
+++ b/__mocks__/languages.json
@@ -0,0 +1,10 @@
+{
+  "en": {
+    "fileName": "en_EN.json",
+    "label": "English"
+  },
+  "en-us": {
+    "fileName": "en_US.json",
+    "label": "English (US)"
+  }
+}
diff --git a/package.json b/package.json
index d6cb56b136..a2d042a6b8 100644
--- a/package.json
+++ b/package.json
@@ -161,7 +161,11 @@
     ],
     "setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
     "moduleNameMapper": {
-      "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js"
-    }
+      "\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js",
+      "\\$webapp/i18n/languages.json": "<rootDir>/__mocks__/languages.json"
+    },
+    "transformIgnorePatterns": [
+      "/node_modules/(?!matrix-js-sdk).+$"
+    ]
   }
 }

From 4dfbce31085adccd48079c766b6323d67494eb33 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:22:50 -0700
Subject: [PATCH 63/86] Fix languageHandler's use of $webapp languages.json for
 Jest

---
 src/languageHandler.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/languageHandler.js b/src/languageHandler.js
index 3a061df915..ddb7e2718c 100644
--- a/src/languageHandler.js
+++ b/src/languageHandler.js
@@ -419,9 +419,9 @@ export function pickBestLanguage(langs) {
 function getLangsJson() {
     return new Promise(async (resolve, reject) => {
         let url;
-        try {
+        if (typeof(webpackLangJsonUrl) === 'string') { // in Jest this 'url' isn't a URL, so just fall through
             url = webpackLangJsonUrl;
-        } catch (e) {
+        } else {
             url = i18nFolder + 'languages.json';
         }
         request(

From 54f3288dea791fb272cb7f18bba6c8d1bf7323e0 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:23:27 -0700
Subject: [PATCH 64/86] Fix imports for tests

This doesn't fix the fact that someone called it "peg".
---
 test/components/views/messages/TextualBody-test.js | 2 +-
 test/components/views/rooms/RoomSettings-test.js   | 2 +-
 test/stores/RoomViewStore-test.js                  | 2 +-
 test/test-utils.js                                 | 5 ++---
 test/utils/permalinks/Permalinks-test.js           | 2 +-
 5 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/test/components/views/messages/TextualBody-test.js b/test/components/views/messages/TextualBody-test.js
index 7aeff94404..443aa7e121 100644
--- a/test/components/views/messages/TextualBody-test.js
+++ b/test/components/views/messages/TextualBody-test.js
@@ -21,7 +21,7 @@ import { configure, mount } from "enzyme";
 
 import sdk from "../../../skinned-sdk";
 import {mkEvent, mkStubRoom} from "../../../test-utils";
-import MatrixClientPeg from "../../../../src/MatrixClientPeg";
+import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
 import * as languageHandler from "../../../../src/languageHandler";
 
 const TextualBody = sdk.getComponent("views.messages.TextualBody");
diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js
index a89508fe98..21d22a964c 100644
--- a/test/components/views/rooms/RoomSettings-test.js
+++ b/test/components/views/rooms/RoomSettings-test.js
@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom';
 import jest from 'jest-mock';
 import * as testUtils from '../../../test-utils';
 import sdk from '../../../skinned-sdk';
-import MatrixClientPeg from '../../../../src/MatrixClientPeg';
+import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
 import SettingsStore from '../../../../src/settings/SettingsStore';
 
 
diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js
index f227ae69ab..41252103e7 100644
--- a/test/stores/RoomViewStore-test.js
+++ b/test/stores/RoomViewStore-test.js
@@ -1,6 +1,6 @@
 import RoomViewStore from '../../src/stores/RoomViewStore';
 
-import peg from '../../src/MatrixClientPeg';
+import {MatrixClientPeg as peg} from '../../src/MatrixClientPeg';
 
 import * as testUtils from '../test-utils';
 
diff --git a/test/test-utils.js b/test/test-utils.js
index eadda2fa7e..fdd50a8792 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -1,14 +1,13 @@
 "use strict";
 
 import React from 'react';
-import peg from '../src/MatrixClientPeg';
+import {MatrixClientPeg as peg} from '../src/MatrixClientPeg';
 import dis from '../src/dispatcher';
-import jssdk from 'matrix-js-sdk';
 import {makeType} from "../src/utils/TypeUtils";
 import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils";
 import ShallowRenderer from 'react-test-renderer/shallow';
 import MatrixClientContext from "../src/contexts/MatrixClientContext";
-const MatrixEvent = jssdk.MatrixEvent;
+import {MatrixEvent} from "matrix-js-sdk/src/models/event";
 
 export function getRenderer() {
     // Old: ReactTestUtils.createRenderer();
diff --git a/test/utils/permalinks/Permalinks-test.js b/test/utils/permalinks/Permalinks-test.js
index 05be3a6e5b..72cd66cb69 100644
--- a/test/utils/permalinks/Permalinks-test.js
+++ b/test/utils/permalinks/Permalinks-test.js
@@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import peg from '../../../src/MatrixClientPeg';
+import {MatrixClientPeg as peg} from '../../../src/MatrixClientPeg';
 import {
     makeGroupPermalink,
     makeRoomPermalink,

From 4bc5ada50e96d6d307dc70f29156962ef740af9b Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:23:46 -0700
Subject: [PATCH 65/86] Fix test bootstrap for new skinning approach

---
 test/skinned-sdk.js | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/test/skinned-sdk.js b/test/skinned-sdk.js
index 1ad361d59d..bc13d78815 100644
--- a/test/skinned-sdk.js
+++ b/test/skinned-sdk.js
@@ -9,16 +9,10 @@
  * app to provide
  */
 
-// for ES6 stuff like startsWith() and Object.values() that babel doesn't do by
-// default
-require('babel-polyfill');
+import * as sdk from "../src/index";
+import stubComponent from "./components/stub-component";
 
-const sdk = require("../src/index");
-
-const skin = require('../src/component-index.js');
-const stubComponent = require('./components/stub-component.js');
-
-const components = skin.components;
+const components = {};
 components['structures.LeftPanel'] = stubComponent();
 components['structures.RightPanel'] = stubComponent();
 components['structures.RoomDirectory'] = stubComponent();
@@ -31,6 +25,6 @@ components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'Mes
 components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'});
 components['views.rooms.SearchBar'] = stubComponent();
 
-sdk.loadSkin(skin);
+sdk.loadSkin({components});
 
-module.exports = sdk;
+export default sdk;

From aa389461667396224701f17c0884ca0cd628287a Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:24:13 -0700
Subject: [PATCH 66/86] Actually define some tests in TextualBody's test

Jest really wants you to do things the right way.
---
 .../views/messages/TextualBody-test.js        | 44 ++++++++++---------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/test/components/views/messages/TextualBody-test.js b/test/components/views/messages/TextualBody-test.js
index 443aa7e121..755751ffb7 100644
--- a/test/components/views/messages/TextualBody-test.js
+++ b/test/components/views/messages/TextualBody-test.js
@@ -33,7 +33,7 @@ describe("<TextualBody />", () => {
         MatrixClientPeg.matrixClient = null;
     });
 
-    describe("renders m.emote correctly", () => {
+    it("renders m.emote correctly", () => {
         MatrixClientPeg.matrixClient = {
             getRoom: () => mkStubRoom("room_id"),
             getAccountData: () => undefined,
@@ -56,7 +56,7 @@ describe("<TextualBody />", () => {
         expect(content.html()).toBe('<span class="mx_EventTile_body" dir="auto">winks</span>');
     });
 
-    describe("renders m.notice correctly", () => {
+    it("renders m.notice correctly", () => {
         MatrixClientPeg.matrixClient = {
             getRoom: () => mkStubRoom("room_id"),
             getAccountData: () => undefined,
@@ -80,12 +80,14 @@ describe("<TextualBody />", () => {
     });
 
     describe("renders plain-text m.text correctly", () => {
-        MatrixClientPeg.matrixClient = {
-            getRoom: () => mkStubRoom("room_id"),
-            getAccountData: () => undefined,
-        };
+        beforeEach(() => {
+            MatrixClientPeg.matrixClient = {
+                getRoom: () => mkStubRoom("room_id"),
+                getAccountData: () => undefined,
+            };
+        });
 
-        describe("simple message renders as expected", () => {
+        it("simple message renders as expected", () => {
             const ev = mkEvent({
                 type: "m.room.message",
                 room: "room_id",
@@ -104,7 +106,7 @@ describe("<TextualBody />", () => {
         });
 
         // If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
-        describe("linkification get applied correctly into the DOM", () => {
+        it("linkification get applied correctly into the DOM", () => {
             const ev = mkEvent({
                 type: "m.room.message",
                 room: "room_id",
@@ -126,16 +128,18 @@ describe("<TextualBody />", () => {
     });
 
     describe("renders formatted m.text correctly", () => {
-        MatrixClientPeg.matrixClient = {
-            getRoom: () => mkStubRoom("room_id"),
-            getAccountData: () => undefined,
-            getUserId: () => "@me:my_server",
-            getHomeserverUrl: () => "https://my_server/",
-            on: () => undefined,
-            removeListener: () => undefined,
-        };
+        beforeEach(() => {
+            MatrixClientPeg.matrixClient = {
+                getRoom: () => mkStubRoom("room_id"),
+                getAccountData: () => undefined,
+                getUserId: () => "@me:my_server",
+                getHomeserverUrl: () => "https://my_server/",
+                on: () => undefined,
+                removeListener: () => undefined,
+            };
+        });
 
-        describe("italics, bold, underline and strikethrough render as expected", () => {
+        it("italics, bold, underline and strikethrough render as expected", () => {
             const ev = mkEvent({
                 type: "m.room.message",
                 room: "room_id",
@@ -156,7 +160,7 @@ describe("<TextualBody />", () => {
                 ev.getContent().formatted_body + '</span>');
         });
 
-        describe("spoilers get injected properly into the DOM", () => {
+        it("spoilers get injected properly into the DOM", () => {
             const ev = mkEvent({
                 type: "m.room.message",
                 room: "room_id",
@@ -182,7 +186,7 @@ describe("<TextualBody />", () => {
         });
 
         // If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
-        describe("pills get injected correctly into the DOM", () => {
+        it("pills get injected correctly into the DOM", () => {
             const ev = mkEvent({
                 type: "m.room.message",
                 room: "room_id",
@@ -208,7 +212,7 @@ describe("<TextualBody />", () => {
         });
     });
 
-    describe("renders url previews correctly", () => {
+    it("renders url previews correctly", () => {
         languageHandler.setMissingEntryGenerator(key => key.split('|', 2)[1]);
 
         MatrixClientPeg.matrixClient = {

From d7dd67f69e7644130b28e914fd26f0f0359c7981 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:28:32 -0700
Subject: [PATCH 67/86] Remove subtly irrelevant package

---
 package.json |  1 -
 yarn.lock    | 56 ----------------------------------------------------
 2 files changed, 57 deletions(-)

diff --git a/package.json b/package.json
index a2d042a6b8..7abb9bcaaa 100644
--- a/package.json
+++ b/package.json
@@ -148,7 +148,6 @@
     "stylelint": "^9.10.1",
     "stylelint-config-standard": "^18.2.0",
     "stylelint-scss": "^3.9.0",
-    "subtle": "^0.1.8",
     "tslint": "^5.20.1",
     "typescript": "^3.7.3",
     "walk": "^2.3.9",
diff --git a/yarn.lock b/yarn.lock
index e7998243eb..6655f9663e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1884,11 +1884,6 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
-bluebird@^2.9.27:
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
-  integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
-
 bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -2933,13 +2928,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
-ecc-jsbn@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.0.1.tgz#970577ba31b4976fb1889a298cb7451d896c466d"
-  integrity sha1-lwV3ujG0l2+xiJopjLdFHYlsRm0=
-  dependencies:
-    jsbn "git+https://github.com/rynomad/jsbn.git"
-
 ecc-jsbn@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@@ -2948,12 +2936,6 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
-"ecc-qj@git+https://github.com/rynomad/ecc.git":
-  version "0.0.1"
-  resolved "git+https://github.com/rynomad/ecc.git#a8c599363dab87a5c95274338d863233f00f7c4a"
-  dependencies:
-    nan "^1.6.2"
-
 electron-to-chromium@^1.3.317, electron-to-chromium@^1.3.322:
   version "1.3.322"
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
@@ -5261,10 +5243,6 @@ js-yaml@^3.13.0, js-yaml@^3.13.1:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
-"jsbn@git+https://github.com/rynomad/jsbn.git":
-  version "0.0.0"
-  resolved "git+https://github.com/rynomad/jsbn.git#bb522b0124f75424f89d49446c40a87111942c7b"
-
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -5958,11 +5936,6 @@ mute-stream@0.0.7:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
-nan@^1.6.2:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/nan/-/nan-1.9.0.tgz#1a9cd2755609766f5c291e4194fce39fde286515"
-  integrity sha1-GpzSdVYJdm9cKR5BlPzjn94oZRU=
-
 nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
@@ -6037,11 +6010,6 @@ node-fetch@^1.0.1:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
-node-forge@^0.6.20:
-  version "0.6.49"
-  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.49.tgz#f1ee95d5d74623938fe19d698aa5a26d54d2f60f"
-  integrity sha1-8e6V1ddGI5OP4Z1piqWibVTS9g8=
-
 node-int64@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -6655,13 +6623,6 @@ png-chunks-extract@^1.0.0:
   dependencies:
     crc-32 "^0.3.0"
 
-polyfill-promise@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/polyfill-promise/-/polyfill-promise-4.0.1.tgz#f8448dc27c3b967d5f67fc060f56ed64e2286b49"
-  integrity sha1-+ESNwnw7ln1fZ/wGD1btZOIoa0k=
-  dependencies:
-    bluebird "^2.9.27"
-
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -7749,11 +7710,6 @@ sisteransi@^1.0.3:
   resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3"
   integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==
 
-sjcl@^1.0.3:
-  version "1.0.8"
-  resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
-  integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
-
 slash@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
@@ -8241,18 +8197,6 @@ stylelint@^9.10.1:
     svg-tags "^1.0.0"
     table "^5.0.0"
 
-subtle@^0.1.8:
-  version "0.1.8"
-  resolved "https://registry.yarnpkg.com/subtle/-/subtle-0.1.8.tgz#0c12599b9cf13127eda11626510cd8f24f878916"
-  integrity sha1-DBJZm5zxMSftoRYmUQzY8k+HiRY=
-  dependencies:
-    ecc-jsbn "0.0.1"
-    node-forge "^0.6.20"
-    polyfill-promise "^4.0.1"
-    sjcl "^1.0.3"
-  optionalDependencies:
-    ecc-qj "git+https://github.com/rynomad/ecc.git"
-
 sugarss@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"

From 4b65cdf3f2c2ea42179ce4d38b70a44b218b3fd9 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:40:57 -0700
Subject: [PATCH 68/86] Regenerate i18n

Apparently we need to do this.
---
 src/i18n/strings/en_EN.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 4311733b51..b2d4c61579 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1249,6 +1249,7 @@
     "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.",
     "collapse": "collapse",
     "expand": "expand",
+    "Communities": "Communities",
     "You cannot delete this image. (%(code)s)": "You cannot delete this image. (%(code)s)",
     "Uploaded on %(date)s by %(user)s": "Uploaded on %(date)s by %(user)s",
     "Rotate Left": "Rotate Left",
@@ -1766,7 +1767,6 @@
     "Did you know: you can use communities to filter your Riot.im experience!": "Did you know: you can use communities to filter your Riot.im experience!",
     "To set up a filter, drag a community avatar over to the filter panel on the far left hand side of the screen. You can click on an avatar in the filter panel at any time to see only the rooms and people associated with that community.": "To set up a filter, drag a community avatar over to the filter panel on the far left hand side of the screen. You can click on an avatar in the filter panel at any time to see only the rooms and people associated with that community.",
     "Error whilst fetching joined communities": "Error whilst fetching joined communities",
-    "Communities": "Communities",
     "Create a new community": "Create a new community",
     "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.",
     "You have no visible notifications": "You have no visible notifications",

From 9f04f94c65843f66eb6187442c39a2d5eaeab01e Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Thu, 9 Jan 2020 17:55:57 -0700
Subject: [PATCH 69/86] Enable e2e and Riot tests, removing Karma

---
 .buildkite/pipeline.yaml | 115 +++++++++++++++------------------------
 1 file changed, 44 insertions(+), 71 deletions(-)

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index f1b436338a..e5ee817934 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -54,77 +54,50 @@ steps:
       - docker#v3.0.1:
           image: "node:12"
 
-#  - label: ":chains: End-to-End Tests"
-#    agents:
-#      # We use a xlarge sized instance instead of the normal small ones because
-#      # e2e tests otherwise take +-8min
-#      queue: "xlarge"
-#    command:
-#      # TODO: Remove hacky chmod for BuildKite
-#      - "echo '--- Setup'"
-#      - "chmod +x ./scripts/ci/*.sh"
-#      - "chmod +x ./scripts/*"
-#      - "echo '--- Install js-sdk'"
-#      - "./scripts/ci/install-deps.sh"
-#      - "./scripts/ci/end-to-end-tests.sh"
-#    plugins:
-#      - docker#v3.0.1:
-#          image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
-#          propagate-environment: true
-#
-#  - label: ":karma: Tests"
-#    agents:
-#      # We use a medium sized instance instead of the normal small ones because
-#      # webpack loves to gorge itself on resources.
-#      queue: "medium"
-#    command:
-#      # Install chrome
-#      - "echo '--- Installing Chrome'"
-#      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
-#      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
-#      - "apt-get update"
-#      - "apt-get install -y google-chrome-stable"
-#      # Run tests
-#      # TODO: Remove hacky chmod for BuildKite
-#      - "chmod +x ./scripts/ci/*.sh"
-#      - "chmod +x ./scripts/*"
-#      - "echo '--- Installing Dependencies'"
-#      - "./scripts/ci/install-deps.sh"
-#      - "echo '+++ Running Tests'"
-#      - "./scripts/ci/unit-tests.sh"
-#    env:
-#      CHROME_BIN: "/usr/bin/google-chrome-stable"
-#    plugins:
-#      - docker#v3.0.1:
-#          image: "node:10"
-#          propagate-environment: true
-#
-#  - label: "🔧 Riot Tests"
-#    agents:
-#      # We use a medium sized instance instead of the normal small ones because
-#      # webpack loves to gorge itself on resources.
-#      queue: "medium"
-#    command:
-#      # Install chrome
-#      - "echo '--- Installing Chrome'"
-#      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
-#      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
-#      - "apt-get update"
-#      - "apt-get install -y google-chrome-stable"
-#      # Run tests
-#      # TODO: Remove hacky chmod for BuildKite
-#      - "chmod +x ./scripts/ci/*.sh"
-#      - "chmod +x ./scripts/*"
-#      - "echo '--- Installing Dependencies'"
-#      - "./scripts/ci/install-deps.sh"
-#      - "echo '+++ Running Tests'"
-#      - "./scripts/ci/riot-unit-tests.sh"
-#    env:
-#      CHROME_BIN: "/usr/bin/google-chrome-stable"
-#    plugins:
-#      - docker#v3.0.1:
-#          image: "node:10"
-#          propagate-environment: true
+  - label: ":chains: End-to-End Tests"
+    agents:
+      # We use a xlarge sized instance instead of the normal small ones because
+      # e2e tests otherwise take +-8min
+      queue: "xlarge"
+    command:
+      # TODO: Remove hacky chmod for BuildKite
+      - "echo '--- Setup'"
+      - "chmod +x ./scripts/ci/*.sh"
+      - "chmod +x ./scripts/*"
+      - "echo '--- Install js-sdk'"
+      - "./scripts/ci/install-deps.sh"
+      - "./scripts/ci/end-to-end-tests.sh"
+    plugins:
+      - docker#v3.0.1:
+          image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
+          propagate-environment: true
+
+  - label: "🔧 Riot Tests"
+    agents:
+      # We use a medium sized instance instead of the normal small ones because
+      # webpack loves to gorge itself on resources.
+      queue: "medium"
+    command:
+      # Install chrome
+      - "echo '--- Installing Chrome'"
+      - "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
+      - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
+      - "apt-get update"
+      - "apt-get install -y google-chrome-stable"
+      # Run tests
+      # TODO: Remove hacky chmod for BuildKite
+      - "chmod +x ./scripts/ci/*.sh"
+      - "chmod +x ./scripts/*"
+      - "echo '--- Installing Dependencies'"
+      - "./scripts/ci/install-deps.sh"
+      - "echo '+++ Running Tests'"
+      - "./scripts/ci/riot-unit-tests.sh"
+    env:
+      CHROME_BIN: "/usr/bin/google-chrome-stable"
+    plugins:
+      - docker#v3.0.1:
+          image: "node:10"
+          propagate-environment: true
 
   - label: "🌐 i18n"
     command:

From e66f2a6c3ff76c434c5e9490a2f8aec4271cff47 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 10 Jan 2020 10:13:41 -0700
Subject: [PATCH 70/86] Revert ES6ification of end-to-end tests and add
 instructions for Windows

Because the tests are run directly by node, we have to use the CommonJS module syntax. We could run the thing through babel, but then we just have another babel.

Windows instructions are from experience and may not be optimized.
---
 test/end-to-end-tests/Windows.md              | 39 +++++++++++++++++++
 test/end-to-end-tests/src/logbuffer.js        |  2 +-
 test/end-to-end-tests/src/logger.js           |  2 +-
 test/end-to-end-tests/src/rest/consent.js     |  4 +-
 test/end-to-end-tests/src/rest/creator.js     | 14 +++----
 test/end-to-end-tests/src/rest/multi.js       |  2 +-
 test/end-to-end-tests/src/rest/room.js        |  2 +-
 test/end-to-end-tests/src/rest/session.js     |  2 +-
 .../src/scenarios/directory.js                |  2 +-
 .../src/scenarios/e2e-encryption.js           |  2 +-
 .../src/scenarios/lazy-loading.js             |  2 +-
 test/end-to-end-tests/src/session.js          |  2 +-
 .../src/usecases/accept-invite.js             |  4 +-
 .../src/usecases/create-room.js               |  6 ++-
 test/end-to-end-tests/src/usecases/dialog.js  | 12 ++++--
 test/end-to-end-tests/src/usecases/invite.js  |  2 +-
 test/end-to-end-tests/src/usecases/join.js    |  2 +-
 .../src/usecases/memberlist.js                | 12 ++++--
 .../src/usecases/room-settings.js             |  2 +-
 .../end-to-end-tests/src/usecases/settings.js |  8 ++--
 test/end-to-end-tests/src/usecases/signup.js  |  2 +-
 .../end-to-end-tests/src/usecases/timeline.js | 14 +++----
 test/end-to-end-tests/src/usecases/verify.js  |  8 ++--
 test/end-to-end-tests/src/util.js             |  8 ++--
 24 files changed, 103 insertions(+), 52 deletions(-)
 create mode 100644 test/end-to-end-tests/Windows.md

diff --git a/test/end-to-end-tests/Windows.md b/test/end-to-end-tests/Windows.md
new file mode 100644
index 0000000000..dee4fabb3f
--- /dev/null
+++ b/test/end-to-end-tests/Windows.md
@@ -0,0 +1,39 @@
+# Running the end-to-end tests on Windows
+
+Windows is not the best platform to run the tests on, but if you have to, enable Windows Subsystem for Linux (WSL)
+and start following these steps to get going:
+
+1. Navigate to your working directory (`cd /mnt/c/users/travisr/whatever/matrix-react-sdk` for example).
+2. Run `sudo apt-get install unzip python3 virtualenv dos2unix`
+3. Run `dos2unix ./test/end-to-end-tests/*.sh ./test/end-to-end-tests/synapse/*.sh ./test/end-to-end-tests/riot/*.sh`
+4. Install NodeJS for ubuntu: 
+   ```bash
+   curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
+   sudo apt-get update
+   sudo apt-get install nodejs
+   ```
+5. Start Riot on Windows through `yarn start`
+6. While that builds... Run:
+   ```bash
+   sudo apt-get install x11-apps
+   wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
+   sudo dpkg -i google-chrome-stable_current_amd64.deb
+   sudo apt -f install
+   ```
+7. Run: 
+   ```bash
+   cd ./test/end-to-end-tests
+   ./synapse/install.sh
+   ./run.sh --riot-url http://localhost:8080 --no-sandbox
+   ```
+
+Note that using `yarn test:e2e` probably won't work for you. You might also have to use the config.json from the
+`riot/config-template` directory in order to actually succeed at the tests.
+
+Also note that you'll have to use `--no-sandbox` otherwise Chrome will complain that there's no sandbox available. You
+could probably fix this with enough effort, or you could run a headless Chrome in the WSL container without a sandbox.
+
+
+Reference material that isn't fully represented in the steps above (but snippets have been borrowed):
+* https://virtualizationreview.com/articles/2017/02/08/graphical-programs-on-windows-subsystem-on-linux.aspx
+* https://gist.github.com/drexler/d70ab957f964dbef1153d46bd853c775
diff --git a/test/end-to-end-tests/src/logbuffer.js b/test/end-to-end-tests/src/logbuffer.js
index db4be33e8d..873363c2ec 100644
--- a/test/end-to-end-tests/src/logbuffer.js
+++ b/test/end-to-end-tests/src/logbuffer.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export default class LogBuffer {
+module.exports = class LogBuffer {
     constructor(page, eventName, eventMapper, reduceAsync=false, initialValue = "") {
         this.buffer = initialValue;
         page.on(eventName, (arg) => {
diff --git a/test/end-to-end-tests/src/logger.js b/test/end-to-end-tests/src/logger.js
index 42a9544e4d..f5a338e2c7 100644
--- a/test/end-to-end-tests/src/logger.js
+++ b/test/end-to-end-tests/src/logger.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export default class Logger {
+module.exports = class Logger {
     constructor(username) {
         this.indent = 0;
         this.username = username;
diff --git a/test/end-to-end-tests/src/rest/consent.js b/test/end-to-end-tests/src/rest/consent.js
index 5c424cd6e8..956441571b 100644
--- a/test/end-to-end-tests/src/rest/consent.js
+++ b/test/end-to-end-tests/src/rest/consent.js
@@ -19,7 +19,7 @@ const request = require('request-promise-native');
 const cheerio = require('cheerio');
 const url = require("url");
 
-export async function approveConsent(consentUrl) {
+module.exports.approveConsent = async function(consentUrl) {
     const body = await request.get(consentUrl);
     const doc = cheerio.load(body);
     const v = doc("input[name=v]").val();
@@ -28,4 +28,4 @@ export async function approveConsent(consentUrl) {
     const formAction = doc("form").attr("action");
     const absAction = url.resolve(consentUrl, formAction);
     await request.post(absAction).form({v, u, h});
-}
+};
diff --git a/test/end-to-end-tests/src/rest/creator.js b/test/end-to-end-tests/src/rest/creator.js
index c4ddee0581..03b2e099bc 100644
--- a/test/end-to-end-tests/src/rest/creator.js
+++ b/test/end-to-end-tests/src/rest/creator.js
@@ -32,7 +32,7 @@ function execAsync(command, options) {
     });
 }
 
-export default class RestSessionCreator {
+module.exports = class RestSessionCreator {
     constructor(synapseSubdir, hsUrl, cwd) {
         this.synapseSubdir = synapseSubdir;
         this.hsUrl = hsUrl;
@@ -72,12 +72,12 @@ export default class RestSessionCreator {
 
     async _authenticate(username, password) {
         const requestBody = {
-          "type": "m.login.password",
-          "identifier": {
-            "type": "m.id.user",
-            "user": username,
-          },
-          "password": password,
+            "type": "m.login.password",
+            "identifier": {
+                "type": "m.id.user",
+                "user": username,
+            },
+            "password": password,
         };
         const url = `${this.hsUrl}/_matrix/client/r0/login`;
         const responseBody = await request.post({url, json: true, body: requestBody});
diff --git a/test/end-to-end-tests/src/rest/multi.js b/test/end-to-end-tests/src/rest/multi.js
index d4cd5c765c..570879bff7 100644
--- a/test/end-to-end-tests/src/rest/multi.js
+++ b/test/end-to-end-tests/src/rest/multi.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const Logger = require('../logger');
 
-export default class RestMultiSession {
+module.exports = class RestMultiSession {
     constructor(sessions, groupName) {
         this.log = new Logger(groupName);
         this.sessions = sessions;
diff --git a/test/end-to-end-tests/src/rest/room.js b/test/end-to-end-tests/src/rest/room.js
index b3ba725336..94afce1dac 100644
--- a/test/end-to-end-tests/src/rest/room.js
+++ b/test/end-to-end-tests/src/rest/room.js
@@ -18,7 +18,7 @@ limitations under the License.
 const uuidv4 = require('uuid/v4');
 
 /* no pun intented */
-export default class RestRoom {
+module.exports = class RestRoom {
     constructor(session, roomId, log) {
         this.session = session;
         this._roomId = roomId;
diff --git a/test/end-to-end-tests/src/rest/session.js b/test/end-to-end-tests/src/rest/session.js
index 344493968c..5b97824f5c 100644
--- a/test/end-to-end-tests/src/rest/session.js
+++ b/test/end-to-end-tests/src/rest/session.js
@@ -19,7 +19,7 @@ const Logger = require('../logger');
 const RestRoom = require('./room');
 const {approveConsent} = require('./consent');
 
-export default class RestSession {
+module.exports = class RestSession {
     constructor(credentials) {
         this.log = new Logger(credentials.userId);
         this._credentials = credentials;
diff --git a/test/end-to-end-tests/src/scenarios/directory.js b/test/end-to-end-tests/src/scenarios/directory.js
index cf995ae1a8..ca2f99f192 100644
--- a/test/end-to-end-tests/src/scenarios/directory.js
+++ b/test/end-to-end-tests/src/scenarios/directory.js
@@ -22,7 +22,7 @@ const {receiveMessage} = require('../usecases/timeline');
 const {createRoom} = require('../usecases/create-room');
 const changeRoomSettings = require('../usecases/room-settings');
 
-export default async function roomDirectoryScenarios(alice, bob) {
+module.exports = async function roomDirectoryScenarios(alice, bob) {
     console.log(" creating a public room and join through directory:");
     const room = 'test';
     await createRoom(alice, room);
diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js
index 2a002da66b..2f08acf417 100644
--- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js
+++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js
@@ -24,7 +24,7 @@ const changeRoomSettings = require('../usecases/room-settings');
 const {startSasVerifcation, acceptSasVerification} = require('../usecases/verify');
 const assert = require('assert');
 
-export default async function e2eEncryptionScenarios(alice, bob) {
+module.exports = async function e2eEncryptionScenarios(alice, bob) {
     console.log(" creating an e2e encrypted room and join through invite:");
     const room = "secrets";
     await createRoom(bob, room);
diff --git a/test/end-to-end-tests/src/scenarios/lazy-loading.js b/test/end-to-end-tests/src/scenarios/lazy-loading.js
index 651397e426..0c45b0d083 100644
--- a/test/end-to-end-tests/src/scenarios/lazy-loading.js
+++ b/test/end-to-end-tests/src/scenarios/lazy-loading.js
@@ -28,7 +28,7 @@ const {getMembersInMemberlist} = require('../usecases/memberlist');
 const changeRoomSettings = require('../usecases/room-settings');
 const assert = require('assert');
 
-export default async function lazyLoadingScenarios(alice, bob, charlies) {
+module.exports = async function lazyLoadingScenarios(alice, bob, charlies) {
     console.log(" creating a room for lazy loading member scenarios:");
     const charly1to5 = charlies.slice("charly-1..5", 0, 5);
     const charly6to10 = charlies.slice("charly-6..10", 5);
diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js
index b17e55efa4..f25c5056ad 100644
--- a/test/end-to-end-tests/src/session.js
+++ b/test/end-to-end-tests/src/session.js
@@ -22,7 +22,7 @@ const {delay} = require('./util');
 
 const DEFAULT_TIMEOUT = 20000;
 
-export default class RiotSession {
+module.exports = class RiotSession {
     constructor(browser, page, username, riotserver, hsUrl) {
         this.browser = browser;
         this.page = page;
diff --git a/test/end-to-end-tests/src/usecases/accept-invite.js b/test/end-to-end-tests/src/usecases/accept-invite.js
index d17f583a77..3f208cc1fc 100644
--- a/test/end-to-end-tests/src/usecases/accept-invite.js
+++ b/test/end-to-end-tests/src/usecases/accept-invite.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export default async function acceptInvite(session, name) {
+module.exports = async function acceptInvite(session, name) {
     session.log.step(`accepts "${name}" invite`);
     //TODO: brittle selector
     const invitesHandles = await session.queryAll('.mx_RoomTile_name.mx_RoomTile_invite');
@@ -24,7 +24,7 @@ export default async function acceptInvite(session, name) {
         return {inviteHandle, text};
     }));
     const inviteHandle = invitesWithText.find(({inviteHandle, text}) => {
-    return text.trim() === name;
+        return text.trim() === name;
     }).inviteHandle;
 
     await inviteHandle.click();
diff --git a/test/end-to-end-tests/src/usecases/create-room.js b/test/end-to-end-tests/src/usecases/create-room.js
index 7ca3826c71..140748bca7 100644
--- a/test/end-to-end-tests/src/usecases/create-room.js
+++ b/test/end-to-end-tests/src/usecases/create-room.js
@@ -15,12 +15,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export async function openRoomDirectory(session) {
+async function openRoomDirectory(session) {
     const roomDirectoryButton = await session.query('.mx_LeftPanel_explore .mx_AccessibleButton');
     await roomDirectoryButton.click();
 }
 
-export async function createRoom(session, roomName) {
+async function createRoom(session, roomName) {
     session.log.step(`creates room "${roomName}"`);
 
     const roomListHeaders = await session.queryAll('.mx_RoomSubList_labelContainer');
@@ -43,3 +43,5 @@ export async function createRoom(session, roomName) {
     await session.query('.mx_MessageComposer');
     session.log.done();
 }
+
+module.exports = {openRoomDirectory, createRoom};
diff --git a/test/end-to-end-tests/src/usecases/dialog.js b/test/end-to-end-tests/src/usecases/dialog.js
index 72d024fc79..d4ae97dff9 100644
--- a/test/end-to-end-tests/src/usecases/dialog.js
+++ b/test/end-to-end-tests/src/usecases/dialog.js
@@ -17,20 +17,20 @@ limitations under the License.
 
 const assert = require('assert');
 
-export async function assertDialog(session, expectedTitle) {
+async function assertDialog(session, expectedTitle) {
     const titleElement = await session.query(".mx_Dialog .mx_Dialog_title");
     const dialogHeader = await session.innerText(titleElement);
     assert(dialogHeader, expectedTitle);
 }
 
-export async function acceptDialog(session, expectedTitle) {
+async function acceptDialog(session, expectedTitle) {
     const foundDialog = await acceptDialogMaybe(session, expectedTitle);
     if (!foundDialog) {
         throw new Error("could not find a dialog");
     }
 }
 
-export async function acceptDialogMaybe(session, expectedTitle) {
+async function acceptDialogMaybe(session, expectedTitle) {
     let primaryButton = null;
     try {
         primaryButton = await session.query(".mx_Dialog .mx_Dialog_primary");
@@ -43,3 +43,9 @@ export async function acceptDialogMaybe(session, expectedTitle) {
     await primaryButton.click();
     return true;
 }
+
+module.exports = {
+    assertDialog,
+    acceptDialog,
+    acceptDialogMaybe,
+};
diff --git a/test/end-to-end-tests/src/usecases/invite.js b/test/end-to-end-tests/src/usecases/invite.js
index fc91e4ce16..6bee5dfd6f 100644
--- a/test/end-to-end-tests/src/usecases/invite.js
+++ b/test/end-to-end-tests/src/usecases/invite.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export default async function invite(session, userId) {
+module.exports = async function invite(session, userId) {
     session.log.step(`invites "${userId}" to room`);
     await session.delay(1000);
     const memberPanelButton = await session.query(".mx_RightPanel_membersButton");
diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js
index 4fbc134598..655c0be686 100644
--- a/test/end-to-end-tests/src/usecases/join.js
+++ b/test/end-to-end-tests/src/usecases/join.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const {openRoomDirectory} = require('./create-room');
 
-export default async function join(session, roomName) {
+module.exports = async function join(session, roomName) {
     session.log.step(`joins room "${roomName}"`);
     await openRoomDirectory(session);
     const roomInput = await session.query('.mx_DirectorySearchBox input');
diff --git a/test/end-to-end-tests/src/usecases/memberlist.js b/test/end-to-end-tests/src/usecases/memberlist.js
index 8d2aacf35c..e974eea95b 100644
--- a/test/end-to-end-tests/src/usecases/memberlist.js
+++ b/test/end-to-end-tests/src/usecases/memberlist.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-export async function openMemberInfo(session, name) {
+async function openMemberInfo(session, name) {
     const membersAndNames = await getMembersInMemberlist(session);
     const matchingLabel = membersAndNames.filter((m) => {
         return m.displayName === name;
@@ -25,7 +25,9 @@ export async function openMemberInfo(session, name) {
     await matchingLabel.click();
 }
 
-export async function verifyDeviceForUser(session, name, expectedDevice) {
+module.exports.openMemberInfo = openMemberInfo;
+
+module.exports.verifyDeviceForUser = async function(session, name, expectedDevice) {
     session.log.step(`verifies e2e device for ${name}`);
     const membersAndNames = await getMembersInMemberlist(session);
     const matchingLabel = membersAndNames.filter((m) => {
@@ -58,9 +60,9 @@ export async function verifyDeviceForUser(session, name, expectedDevice) {
     const closeMemberInfo = await session.query(".mx_MemberInfo_cancel");
     await closeMemberInfo.click();
     session.log.done();
-}
+};
 
-export async function getMembersInMemberlist(session) {
+async function getMembersInMemberlist(session) {
     const memberPanelButton = await session.query(".mx_RightPanel_membersButton");
     try {
         await session.query(".mx_RightPanel_headerButton_highlight", 500);
@@ -77,3 +79,5 @@ export async function getMembersInMemberlist(session) {
         return {label: el, displayName: await session.innerText(el)};
     }));
 }
+
+module.exports.getMembersInMemberlist = getMembersInMemberlist;
diff --git a/test/end-to-end-tests/src/usecases/room-settings.js b/test/end-to-end-tests/src/usecases/room-settings.js
index c6a84706cf..f526312f8a 100644
--- a/test/end-to-end-tests/src/usecases/room-settings.js
+++ b/test/end-to-end-tests/src/usecases/room-settings.js
@@ -30,7 +30,7 @@ async function setSettingsToggle(session, toggle, enabled) {
     }
 }
 
-export default async function changeRoomSettings(session, settings) {
+module.exports = async function changeRoomSettings(session, settings) {
     session.log.startGroup(`changes the room settings`);
     /// XXX delay is needed here, possibly because the header is being rerendered
     /// click doesn't do anything otherwise
diff --git a/test/end-to-end-tests/src/usecases/settings.js b/test/end-to-end-tests/src/usecases/settings.js
index 411ec3b497..a405fde9fb 100644
--- a/test/end-to-end-tests/src/usecases/settings.js
+++ b/test/end-to-end-tests/src/usecases/settings.js
@@ -29,7 +29,7 @@ async function openSettings(session, section) {
     }
 }
 
-export async function enableLazyLoading(session) {
+module.exports.enableLazyLoading = async function(session) {
     session.log.step(`enables lazy loading of members in the lab settings`);
     const settingsButton = await session.query('.mx_BottomLeftMenu_settings');
     await settingsButton.click();
@@ -39,9 +39,9 @@ export async function enableLazyLoading(session) {
     const closeButton = await session.query(".mx_RoomHeader_cancelButton");
     await closeButton.click();
     session.log.done();
-}
+};
 
-export async function getE2EDeviceFromSettings(session) {
+module.exports.getE2EDeviceFromSettings = async function(session) {
     session.log.step(`gets e2e device/key from settings`);
     await openSettings(session, "security");
     const deviceAndKey = await session.queryAll(".mx_SettingsTab_section .mx_SecurityUserSettingsTab_deviceInfo code");
@@ -52,4 +52,4 @@ export async function getE2EDeviceFromSettings(session) {
     await closeButton.click();
     session.log.done();
     return {id, key};
-}
+};
diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js
index 381b87ec9e..ef8a259091 100644
--- a/test/end-to-end-tests/src/usecases/signup.js
+++ b/test/end-to-end-tests/src/usecases/signup.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-export default async function signup(session, username, password, homeserver) {
+module.exports = async function signup(session, username, password, homeserver) {
     session.log.step("signs up");
     await session.goto(session.url('/#/register'));
     // change the homeserver by clicking the advanced section
diff --git a/test/end-to-end-tests/src/usecases/timeline.js b/test/end-to-end-tests/src/usecases/timeline.js
index 8a18e2653f..3889dce108 100644
--- a/test/end-to-end-tests/src/usecases/timeline.js
+++ b/test/end-to-end-tests/src/usecases/timeline.js
@@ -17,7 +17,7 @@ limitations under the License.
 
 const assert = require('assert');
 
-export async function scrollToTimelineTop(session) {
+module.exports.scrollToTimelineTop = async function(session) {
     session.log.step(`scrolls to the top of the timeline`);
     await session.page.evaluate(() => {
         return Promise.resolve().then(async () => {
@@ -41,9 +41,9 @@ export async function scrollToTimelineTop(session) {
         });
     });
     session.log.done();
-}
+};
 
-export async function receiveMessage(session, expectedMessage) {
+module.exports.receiveMessage = async function(session, expectedMessage) {
     session.log.step(`receives message "${expectedMessage.body}" from ${expectedMessage.sender}`);
     // wait for a response to come in that contains the message
     // crude, but effective
@@ -67,10 +67,10 @@ export async function receiveMessage(session, expectedMessage) {
     });
     assertMessage(lastMessage, expectedMessage);
     session.log.done();
-}
+};
 
 
-export async function checkTimelineContains(session, expectedMessages, sendersDescription) {
+module.exports.checkTimelineContains = async function(session, expectedMessages, sendersDescription) {
     session.log.step(`checks timeline contains ${expectedMessages.length} ` +
         `given messages${sendersDescription ? ` from ${sendersDescription}`:""}`);
     const eventTiles = await getAllEventTiles(session);
@@ -91,7 +91,7 @@ export async function checkTimelineContains(session, expectedMessages, sendersDe
     expectedMessages.forEach((expectedMessage) => {
         const foundMessage = timelineMessages.find((message) => {
             return message.sender === expectedMessage.sender &&
-                   message.body === expectedMessage.body;
+                message.body === expectedMessage.body;
         });
         try {
             assertMessage(foundMessage, expectedMessage);
@@ -102,7 +102,7 @@ export async function checkTimelineContains(session, expectedMessages, sendersDe
     });
 
     session.log.done();
-}
+};
 
 function assertMessage(foundMessage, expectedMessage) {
     assert(foundMessage, `message ${JSON.stringify(expectedMessage)} not found in timeline`);
diff --git a/test/end-to-end-tests/src/usecases/verify.js b/test/end-to-end-tests/src/usecases/verify.js
index a8b71cfe5c..5f507f96e6 100644
--- a/test/end-to-end-tests/src/usecases/verify.js
+++ b/test/end-to-end-tests/src/usecases/verify.js
@@ -38,7 +38,7 @@ async function getSasCodes(session) {
     return sasLabels;
 }
 
-export async function startSasVerifcation(session, name) {
+module.exports.startSasVerifcation = async function(session, name) {
     await startVerification(session, name);
     // expect "Verify device" dialog and click "Begin Verification"
     await assertDialog(session, "Verify device");
@@ -51,9 +51,9 @@ export async function startSasVerifcation(session, name) {
     // click "Got it" when verification is done
     await acceptDialog(session);
     return sasCodes;
-}
+};
 
-export async function acceptSasVerification(session, name) {
+module.exports.acceptSasVerification = async function(session, name) {
     await assertDialog(session, "Incoming Verification Request");
     const opponentLabelElement = await session.query(".mx_IncomingSasDialog_opponentProfile h2");
     const opponentLabel = await session.innerText(opponentLabelElement);
@@ -67,4 +67,4 @@ export async function acceptSasVerification(session, name) {
     // click "Got it" when verification is done
     await acceptDialog(session);
     return sasCodes;
-}
+};
diff --git a/test/end-to-end-tests/src/util.js b/test/end-to-end-tests/src/util.js
index cafe929eca..cc7391fa9f 100644
--- a/test/end-to-end-tests/src/util.js
+++ b/test/end-to-end-tests/src/util.js
@@ -15,14 +15,14 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export function range(start, amount, step = 1) {
+module.exports.range = function(start, amount, step = 1) {
     const r = [];
     for (let i = 0; i < amount; ++i) {
         r.push(start + (i * step));
     }
     return r;
-}
+};
 
-export function delay(ms) {
+module.exports.delay = function(ms) {
     return new Promise((resolve) => setTimeout(resolve, ms));
-}
+};

From c370b28694d7e397078b0a9a2806662bb4eb0baa Mon Sep 17 00:00:00 2001
From: Christopher <kurekc@hotmail.com>
Date: Sun, 12 Jan 2020 16:19:24 +0000
Subject: [PATCH 71/86] #11378. Added cut/copy and pasting user pills from
 editor.

---
 .../views/rooms/BasicMessageComposer.js       | 46 ++++++++++++++++---
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js
index 15585ffea0..94159ec8c3 100644
--- a/src/components/views/rooms/BasicMessageComposer.js
+++ b/src/components/views/rooms/BasicMessageComposer.js
@@ -200,17 +200,47 @@ export default class BasicMessageEditor extends React.Component {
         return !!(this._isIMEComposing || (event.nativeEvent && event.nativeEvent.isComposing));
     }
 
+    _onCutCopy = (event, type) => {
+        const selection = document.getSelection();
+        const text = selection.toString();
+        if (text) {
+            const {model} = this.props;
+            const range = getRangeForSelection(this._editorRef, model, selection);
+            const selectedParts = range.parts.map(p => p.serialize());
+            event.clipboardData.setData("application/x-riot-composer", JSON.stringify(selectedParts));
+            if (type === "cut") {
+                selection.deleteFromDocument();
+                range.replace([]);
+            }
+            event.preventDefault();
+        }
+    }
+
+    _onCopy = (event) => {
+        this._onCutCopy(event, "copy");
+    }
+
+    _onCut = (event) => {
+        this._onCutCopy(event, "cut");
+    }
+
     _onPaste = (event) => {
         const {model} = this.props;
         const {partCreator} = model;
-        const text = event.clipboardData.getData("text/plain");
-        if (text) {
-            this._modifiedFlag = true;
-            const range = getRangeForSelection(this._editorRef, model, document.getSelection());
-            const parts = parsePlainTextMessage(text, partCreator);
-            replaceRangeAndMoveCaret(range, parts);
-            event.preventDefault();
+        const partsText = event.clipboardData.getData("application/x-riot-composer");
+        let parts;
+        if (partsText) {
+            const serializedTextParts = JSON.parse(partsText);
+            const deserializedParts = serializedTextParts.map(p => partCreator.deserializePart(p))
+            parts = deserializedParts;
+        } else {
+            const text = event.clipboardData.getData("text/plain");
+            parts = parsePlainTextMessage(text, partCreator);
         }
+        this._modifiedFlag = true;
+        const range = getRangeForSelection(this._editorRef, model, document.getSelection());
+        replaceRangeAndMoveCaret(range, parts);
+        event.preventDefault();
     }
 
     _onInput = (event) => {
@@ -557,6 +587,8 @@ export default class BasicMessageEditor extends React.Component {
                 tabIndex="0"
                 onBlur={this._onBlur}
                 onFocus={this._onFocus}
+                onCopy={this._onCopy}
+                onCut={this._onCut}
                 onPaste={this._onPaste}
                 onKeyDown={this._onKeyDown}
                 ref={ref => this._editorRef = ref}

From 59ea865e8e5e3f8ff9c2f7990f7213e82a708a20 Mon Sep 17 00:00:00 2001
From: Christopher <kurekc@hotmail.com>
Date: Mon, 13 Jan 2020 14:29:42 +0000
Subject: [PATCH 72/86] Added missing semicolon.

---
 src/components/views/rooms/BasicMessageComposer.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js
index 94159ec8c3..4c3b5d5c2c 100644
--- a/src/components/views/rooms/BasicMessageComposer.js
+++ b/src/components/views/rooms/BasicMessageComposer.js
@@ -231,7 +231,7 @@ export default class BasicMessageEditor extends React.Component {
         let parts;
         if (partsText) {
             const serializedTextParts = JSON.parse(partsText);
-            const deserializedParts = serializedTextParts.map(p => partCreator.deserializePart(p))
+            const deserializedParts = serializedTextParts.map(p => partCreator.deserializePart(p));
             parts = deserializedParts;
         } else {
             const text = event.clipboardData.getData("text/plain");

From bf6798e1096ad0145f2e833239e5135e4309dec9 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 13:28:33 -0700
Subject: [PATCH 73/86] Appease the linter

---
 src/Avatar.js                                       |  3 ++-
 src/Resend.js                                       | 12 ++++++------
 src/components/structures/TimelinePanel.js          |  2 --
 src/components/views/room_settings/AliasSettings.js |  1 +
 test/components/stub-component.js                   |  2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/Avatar.js b/src/Avatar.js
index 47d08aac21..5a330c31e9 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -20,6 +20,7 @@ import DMRoomMap from './utils/DMRoomMap';
 import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 
 export function avatarUrlForMember(member, width, height, resizeMethod) {
+    let url;
     if (member && member.getAvatarUrl) {
         url = member.getAvatarUrl(
             MatrixClientPeg.get().getHomeserverUrl(),
@@ -34,7 +35,7 @@ export function avatarUrlForMember(member, width, height, resizeMethod) {
         // member can be null here currently since on invites, the JS SDK
         // does not have enough info to build a RoomMember object for
         // the inviter.
-        url = this.defaultAvatarUrlForString(member ? member.userId : '');
+        url = defaultAvatarUrlForString(member ? member.userId : '');
     }
     return url;
 }
diff --git a/src/Resend.js b/src/Resend.js
index 1d73212340..6d6c18cf27 100644
--- a/src/Resend.js
+++ b/src/Resend.js
@@ -21,29 +21,29 @@ import { EventStatus } from 'matrix-js-sdk';
 
 export default class Resend {
     static resendUnsentEvents(room) {
-        room.getPendingEvents().filter(function (ev) {
+        room.getPendingEvents().filter(function(ev) {
             return ev.status === EventStatus.NOT_SENT;
-        }).forEach(function (event) {
+        }).forEach(function(event) {
             Resend.resend(event);
         });
     }
 
     static cancelUnsentEvents(room) {
-        room.getPendingEvents().filter(function (ev) {
+        room.getPendingEvents().filter(function(ev) {
             return ev.status === EventStatus.NOT_SENT;
-        }).forEach(function (event) {
+        }).forEach(function(event) {
             Resend.removeFromQueue(event);
         });
     }
 
     static resend(event) {
         const room = MatrixClientPeg.get().getRoom(event.getRoomId());
-        MatrixClientPeg.get().resendEvent(event, room).then(function (res) {
+        MatrixClientPeg.get().resendEvent(event, room).then(function(res) {
             dis.dispatch({
                 action: 'message_sent',
                 event: event,
             });
-        }, function (err) {
+        }, function(err) {
             // XXX: temporary logging to try to diagnose
             // https://github.com/vector-im/riot-web/issues/3148
             console.log('Resend got send failure: ' + err.name + '(' + err + ')');
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 1d50a51579..30b02bfcca 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -1136,8 +1136,6 @@ const TimelinePanel = createReactClass({
         const messagePanel = this._messagePanel.current;
         if (messagePanel === undefined) return null;
 
-        const EventTile = sdk.getComponent('rooms.EventTile');
-
         const wrapperRect = ReactDOM.findDOMNode(messagePanel).getBoundingClientRect();
         const myUserId = MatrixClientPeg.get().credentials.userId;
 
diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js
index b5febb689e..ee5a505b32 100644
--- a/src/components/views/room_settings/AliasSettings.js
+++ b/src/components/views/room_settings/AliasSettings.js
@@ -24,6 +24,7 @@ import { _t } from '../../../languageHandler';
 import Field from "../elements/Field";
 import ErrorDialog from "../dialogs/ErrorDialog";
 import AccessibleButton from "../elements/AccessibleButton";
+import Modal from "../../../Modal";
 
 class EditableAliasesList extends EditableItemList {
     constructor(props) {
diff --git a/test/components/stub-component.js b/test/components/stub-component.js
index 5638ada09d..a5c3b44409 100644
--- a/test/components/stub-component.js
+++ b/test/components/stub-component.js
@@ -17,4 +17,4 @@ export default function(opts) {
     }
 
     return createReactClass(opts);
-};
+}

From 813b14018ed23db5def3a486262ee66a8723be37 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 13:36:35 -0700
Subject: [PATCH 74/86] Fix CI build steps for new environment.

Some of the CI stuff requires the autogenerated files to be present. Easiest way to get them all is to build the thing. Previously this was done in an install stage, but we don't do that anymore.
---
 .buildkite/pipeline.yaml | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml
index e5ee817934..a8ce1273fb 100644
--- a/.buildkite/pipeline.yaml
+++ b/.buildkite/pipeline.yaml
@@ -33,12 +33,13 @@ steps:
       queue: "medium"
     command:
       - "echo '--- Install js-sdk'"
-      # Run tests
       # TODO: Remove hacky chmod for BuildKite
       - "chmod +x ./scripts/ci/*.sh"
       - "chmod +x ./scripts/*"
       - "echo '--- Installing Dependencies'"
       - "./scripts/ci/install-deps.sh"
+      - "echo '--- Running initial build steps'"
+      - "yarn build"
       - "echo '+++ Running Tests'"
       - "yarn test"
     plugins:
@@ -49,6 +50,7 @@ steps:
     command:
       - "echo '--- Install js-sdk'"
       - "./scripts/ci/install-deps.sh"
+      - "echo '+++ Building Project'"
       - "yarn build"
     plugins:
       - docker#v3.0.1:
@@ -66,6 +68,9 @@ steps:
       - "chmod +x ./scripts/*"
       - "echo '--- Install js-sdk'"
       - "./scripts/ci/install-deps.sh"
+      - "echo '--- Running initial build steps'"
+      - "yarn build"
+      - "echo '+++ Running Tests'"
       - "./scripts/ci/end-to-end-tests.sh"
     plugins:
       - docker#v3.0.1:
@@ -84,12 +89,13 @@ steps:
       - "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
       - "apt-get update"
       - "apt-get install -y google-chrome-stable"
-      # Run tests
       # TODO: Remove hacky chmod for BuildKite
       - "chmod +x ./scripts/ci/*.sh"
       - "chmod +x ./scripts/*"
       - "echo '--- Installing Dependencies'"
       - "./scripts/ci/install-deps.sh"
+      - "echo '--- Running initial build steps'"
+      - "yarn build"
       - "echo '+++ Running Tests'"
       - "./scripts/ci/riot-unit-tests.sh"
     env:

From 1e70af00a3b2368660f69d42b7b1760674d0e241 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 17:28:24 -0700
Subject: [PATCH 75/86] Fix GroupView test

It was counting the wrong number of updates for reasons I don't understand.
---
 test/components/structures/GroupView-test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js
index eac471190c..fb942d2f7c 100644
--- a/test/components/structures/GroupView-test.js
+++ b/test/components/structures/GroupView-test.js
@@ -302,7 +302,7 @@ describe('GroupView', function() {
 
     it('should show a RoomDetailList after a successful /summary & /rooms (no rooms returned)', function() {
         const groupView = ReactTestUtils.findRenderedComponentWithType(root, GroupView);
-        const prom = waitForUpdate(groupView, 5).then(() => {
+        const prom = waitForUpdate(groupView, 4).then(() => {
             const roomDetailList = ReactTestUtils.findRenderedDOMComponentWithClass(root, 'mx_RoomDetailList');
             const roomDetailListElement = ReactDOM.findDOMNode(roomDetailList);
             expect(roomDetailListElement).toBeTruthy();

From 90c7535a695cb6111a308683a9189bd3c78646ff Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 17:51:17 -0700
Subject: [PATCH 76/86] Export VIEWS from MatrixChat for riot-web tests

---
 src/components/structures/MatrixChat.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index e88c1bfa16..cca86ff764 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -65,7 +65,7 @@ import { defer } from "../../utils/promise";
 import KeyVerificationStateObserver from '../../utils/KeyVerificationStateObserver';
 
 /** constants for MatrixChat.state.view */
-const VIEWS = {
+export const VIEWS = {
     // a special initial state which is only used at startup, while we are
     // trying to re-animate a matrix client or register as a guest.
     LOADING: 0,

From 9188183c9bc5e00d8bdfaa21415b34151fb82859 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 21:04:13 -0700
Subject: [PATCH 77/86] Improve the quality of invite suggestions by filtering
 out DMs

This helps the small rooms from being scored highly, bringing out users you've not seen in a long while.
---
 src/components/views/dialogs/DMInviteDialog.js | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/components/views/dialogs/DMInviteDialog.js b/src/components/views/dialogs/DMInviteDialog.js
index 371768eb4e..1a6e387f46 100644
--- a/src/components/views/dialogs/DMInviteDialog.js
+++ b/src/components/views/dialogs/DMInviteDialog.js
@@ -332,6 +332,11 @@ export default class DMInviteDialog extends React.PureComponent {
 
         // Generates { userId: {member, rooms[]} }
         const memberRooms = joinedRooms.reduce((members, room) => {
+            // Filter out DMs (we'll handle these in the recents section)
+            if (!!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) {
+                return members; // Do nothing
+            }
+
             const joinedMembers = room.getJoinedMembers().filter(u => !excludedUserIds.includes(u.userId));
             for (const member of joinedMembers) {
                 if (!members[member.userId]) {
@@ -377,6 +382,7 @@ export default class DMInviteDialog extends React.PureComponent {
             }
             return b.score - a.score;
         });
+
         return members.map(m => ({userId: m.member.userId, user: m.member}));
     }
 

From b69b284efa25640c69c7e5a33382bc458021f81e Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 21:20:01 -0700
Subject: [PATCH 78/86] Humanize the recent DM rooms ourselves for translations

---
 package.json                                  |  1 -
 .../views/dialogs/DMInviteDialog.js           |  6 +-
 src/i18n/strings/en_EN.json                   | 14 +++++
 src/utils/humanize.js                         | 57 +++++++++++++++++++
 yarn.lock                                     |  5 --
 5 files changed, 73 insertions(+), 10 deletions(-)
 create mode 100644 src/utils/humanize.js

diff --git a/package.json b/package.json
index 4cbfd84882..df354d3ff6 100644
--- a/package.json
+++ b/package.json
@@ -82,7 +82,6 @@
     "glob-to-regexp": "^0.4.1",
     "highlight.js": "^9.15.8",
     "html-entities": "^1.2.1",
-    "humanize": "^0.0.9",
     "is-ip": "^2.0.0",
     "isomorphic-fetch": "^2.2.1",
     "linkifyjs": "^2.1.6",
diff --git a/src/components/views/dialogs/DMInviteDialog.js b/src/components/views/dialogs/DMInviteDialog.js
index 371768eb4e..54d3ab8337 100644
--- a/src/components/views/dialogs/DMInviteDialog.js
+++ b/src/components/views/dialogs/DMInviteDialog.js
@@ -22,7 +22,6 @@ import MatrixClientPeg from "../../../MatrixClientPeg";
 import {makeUserPermalink} from "../../../utils/permalinks/Permalinks";
 import DMRoomMap from "../../../utils/DMRoomMap";
 import {RoomMember} from "matrix-js-sdk/lib/matrix";
-import * as humanize from "humanize";
 import SdkConfig from "../../../SdkConfig";
 import {getHttpUriForMxc} from "matrix-js-sdk/lib/content-repo";
 import * as Email from "../../../email";
@@ -31,6 +30,7 @@ import {abbreviateUrl} from "../../../utils/UrlUtils";
 import dis from "../../../dispatcher";
 import IdentityAuthClient from "../../../IdentityAuthClient";
 import Modal from "../../../Modal";
+import {humanizeTime} from "../../../utils/humanize";
 
 // TODO: [TravisR] Make this generic for all kinds of invites
 
@@ -226,9 +226,7 @@ class DMRoomTile extends React.PureComponent {
 
         let timestamp = null;
         if (this.props.lastActiveTs) {
-            // TODO: [TravisR] Figure out how to i18n this
-            // `humanize` wants seconds for a timestamp, so divide by 1000
-            const humanTs = humanize.relativeTime(this.props.lastActiveTs / 1000);
+            const humanTs = humanizeTime(this.props.lastActiveTs);
             timestamp = <span className='mx_DMInviteDialog_roomTile_time'>{humanTs}</span>;
         }
 
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index e3aaf044c3..b1c8b12d86 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -309,6 +309,20 @@
     "%(items)s and %(count)s others|other": "%(items)s and %(count)s others",
     "%(items)s and %(count)s others|one": "%(items)s and one other",
     "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s",
+    "a few seconds ago": "a few seconds ago",
+    "about a minute ago": "about a minute ago",
+    "%(num)s minutes ago": "%(num)s minutes ago",
+    "about an hour ago": "about an hour ago",
+    "%(num)s hours ago": "%(num)s hours ago",
+    "about a day ago": "about a day ago",
+    "%(num)s days ago": "%(num)s days ago",
+    "a few seconds from now": "a few seconds from now",
+    "about a minute from now": "about a minute from now",
+    "%(num)s minutes from now": "%(num)s minutes from now",
+    "about an hour from now": "about an hour from now",
+    "%(num)s hours from now": "%(num)s hours from now",
+    "about a day from now": "about a day from now",
+    "%(num)s days from now": "%(num)s days from now",
     "%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
     "Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
     "Not a valid Riot keyfile": "Not a valid Riot keyfile",
diff --git a/src/utils/humanize.js b/src/utils/humanize.js
new file mode 100644
index 0000000000..6e6f17f8f4
--- /dev/null
+++ b/src/utils/humanize.js
@@ -0,0 +1,57 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import {_t} from "../languageHandler";
+
+/**
+ * Converts a timestamp into human-readable, translated, text.
+ * @param {number} timeMillis The time in millis to compare against.
+ * @returns {string} The humanized time.
+ */
+export function humanizeTime(timeMillis) {
+    // These are the constants we use for when to break the text
+    const MILLISECONDS_RECENT = 15000;
+    const MILLISECONDS_1_MIN = 75000;
+    const MINUTES_UNDER_1_HOUR = 45;
+    const MINUTES_1_HOUR = 75;
+    const HOURS_UNDER_1_DAY = 23;
+    const HOURS_1_DAY = 26;
+
+    const now = (new Date()).getTime();
+    let msAgo = now - timeMillis;
+    const minutes = Math.abs(Math.ceil(msAgo / 60000));
+    const hours = Math.ceil(minutes / 60);
+    const days = Math.ceil(hours / 24);
+
+    if (msAgo >= 0) { // Past
+        if (msAgo <= MILLISECONDS_RECENT) return _t("a few seconds ago");
+        if (msAgo <= MILLISECONDS_1_MIN) return _t("about a minute ago");
+        if (minutes <= MINUTES_UNDER_1_HOUR) return _t("%(num)s minutes ago", {num: minutes});
+        if (minutes <= MINUTES_1_HOUR) return _t("about an hour ago");
+        if (hours <= HOURS_UNDER_1_DAY) return _t("%(num)s hours ago", {num: hours});
+        if (hours <= HOURS_1_DAY) return _t("about a day ago");
+        return _t("%(num)s days ago", {num: days});
+    } else { // Future
+        msAgo = Math.abs(msAgo);
+        if (msAgo <= MILLISECONDS_RECENT) return _t("a few seconds from now");
+        if (msAgo <= MILLISECONDS_1_MIN) return _t("about a minute from now");
+        if (minutes <= MINUTES_UNDER_1_HOUR) return _t("%(num)s minutes from now", {num: minutes});
+        if (minutes <= MINUTES_1_HOUR) return _t("about an hour from now");
+        if (hours <= HOURS_UNDER_1_DAY) return _t("%(num)s hours from now", {num: hours});
+        if (hours <= HOURS_1_DAY) return _t("about a day from now");
+        return _t("%(num)s days from now", {num: days});
+    }
+}
diff --git a/yarn.lock b/yarn.lock
index 0ea3190258..b31cd3ab4c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4258,11 +4258,6 @@ humanize-ms@^1.2.1:
   dependencies:
     ms "^2.0.0"
 
-humanize@^0.0.9:
-  version "0.0.9"
-  resolved "https://registry.yarnpkg.com/humanize/-/humanize-0.0.9.tgz#1994ffaecdfe9c441ed2bdac7452b7bb4c9e41a4"
-  integrity sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ=
-
 iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"

From 76183fc8fd1a184dd54667efc9dbaab1877fb3e2 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 13 Jan 2020 21:21:18 -0700
Subject: [PATCH 79/86] Appease the linter

---
 src/components/views/dialogs/DMInviteDialog.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/views/dialogs/DMInviteDialog.js b/src/components/views/dialogs/DMInviteDialog.js
index 1a6e387f46..ceab2fea02 100644
--- a/src/components/views/dialogs/DMInviteDialog.js
+++ b/src/components/views/dialogs/DMInviteDialog.js
@@ -333,7 +333,7 @@ export default class DMInviteDialog extends React.PureComponent {
         // Generates { userId: {member, rooms[]} }
         const memberRooms = joinedRooms.reduce((members, room) => {
             // Filter out DMs (we'll handle these in the recents section)
-            if (!!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) {
+            if (DMRoomMap.shared().getUserIdForRoomId(room.roomId)) {
                 return members; // Do nothing
             }
 

From 457e63f24ee79f064679ccc5d7ab48e21e9a357f Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Wed, 15 Jan 2020 10:25:36 -0700
Subject: [PATCH 80/86] Fix reference to js-sdk lint config

---
 .eslintrc.js | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 0721c1c8d2..6a0576c58a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -5,7 +5,10 @@ const path = require('path');
 // but only if they come from a module that starts with eslint-config-
 // So we load the filename directly (and it could be in node_modules/
 // or or ../node_modules/ etc)
-const matrixJsSdkPath = path.dirname(require.resolve('matrix-js-sdk'));
+//
+// We add a `..` to the end because the js-sdk lives out of lib/, but the eslint
+// config is at the project root.
+const matrixJsSdkPath = path.join(path.dirname(require.resolve('matrix-js-sdk')), '..');
 
 module.exports = {
     parser: "babel-eslint",

From 8f37f8638d9009d7bf65e3cbad864133e8d916b3 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Wed, 15 Jan 2020 10:28:27 -0700
Subject: [PATCH 81/86] Build the js-sdk for Jest tests

This is theoretically a fix for the tests failing post-sourcemaps.
---
 scripts/ci/install-deps.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/ci/install-deps.sh b/scripts/ci/install-deps.sh
index 6484ebab29..a2e2e59a45 100755
--- a/scripts/ci/install-deps.sh
+++ b/scripts/ci/install-deps.sh
@@ -7,6 +7,7 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
 pushd matrix-js-sdk
 yarn link
 yarn install
+yarn build
 popd
 
 yarn link matrix-js-sdk

From dd88809622fe350169040efd01af2fa31a8076e1 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Wed, 15 Jan 2020 12:02:23 -0700
Subject: [PATCH 82/86] Fix imports for help & support tab

This was missed, somehow, in the sourcemaps stuff. The tab currently breaks the dialog on load.
---
 .../views/settings/tabs/user/HelpUserSettingsTab.js       | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
index 0cf67a4db7..ab71de86b9 100644
--- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js
@@ -21,10 +21,10 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import SdkConfig from "../../../../../SdkConfig";
 import createRoom from "../../../../../createRoom";
-const packageJson = require('../../../../../../package.json');
-const Modal = require("../../../../../Modal");
-const sdk = require("../../../../..");
-const PlatformPeg = require("../../../../../PlatformPeg");
+import packageJson from "../../../../../../package.json";
+import Modal from "../../../../../Modal";
+import * as sdk from "../../../../../";
+import PlatformPeg from "../../../../../PlatformPeg";
 
 // if this looks like a release, use the 'version' from package.json; else use
 // the git sha. Prepend version with v, to look like riot-web version

From 27ee90cad58666a97e3a61993f3a7c2575753aa2 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Wed, 15 Jan 2020 21:13:56 +0000
Subject: [PATCH 83/86] Add post-login complete security flow

This adds a step after login to complete security for your new session. At the
moment, the only verification method is entering your SSSS passphrase, but nicer
paths will be added soon.

This new step only appears when crypto is available and the account has
cross-signing enabled in SSSS.

Fixes https://github.com/vector-im/riot-web/issues/11214
---
 res/css/_components.scss                      |   1 +
 .../structures/auth/_CompleteSecurity.scss    |  51 ++++++
 src/MatrixClientPeg.js                        |   9 +-
 .../CreateSecretStorageDialog.js              |   2 +-
 src/components/structures/MatrixChat.js       |  90 ++++++---
 .../structures/auth/CompleteSecurity.js       | 173 ++++++++++++++++++
 src/components/structures/auth/SoftLogout.js  |   2 +-
 src/i18n/strings/en_EN.json                   |  10 +-
 src/settings/Settings.js                      |   3 +-
 9 files changed, 309 insertions(+), 32 deletions(-)
 create mode 100644 res/css/structures/auth/_CompleteSecurity.scss
 create mode 100644 src/components/structures/auth/CompleteSecurity.js

diff --git a/res/css/_components.scss b/res/css/_components.scss
index 7a9ebfdf26..a9a114a4cf 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -28,6 +28,7 @@
 @import "./structures/_TopLeftMenuButton.scss";
 @import "./structures/_UploadBar.scss";
 @import "./structures/_ViewSource.scss";
+@import "./structures/auth/_CompleteSecurity.scss";
 @import "./structures/auth/_Login.scss";
 @import "./views/auth/_AuthBody.scss";
 @import "./views/auth/_AuthButtons.scss";
diff --git a/res/css/structures/auth/_CompleteSecurity.scss b/res/css/structures/auth/_CompleteSecurity.scss
new file mode 100644
index 0000000000..c258ce4ec7
--- /dev/null
+++ b/res/css/structures/auth/_CompleteSecurity.scss
@@ -0,0 +1,51 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_CompleteSecurity_header {
+    display: flex;
+    align-items: center;
+}
+
+.mx_CompleteSecurity_headerIcon {
+    width: 24px;
+    height: 24px;
+    margin: 0 4px;
+    position: relative;
+}
+
+.mx_CompleteSecurity_heroIcon {
+    width: 128px;
+    height: 128px;
+    position: relative;
+    margin: 0 auto;
+}
+
+.mx_CompleteSecurity_body {
+    font-size: 15px;
+}
+
+.mx_CompleteSecurity_actionRow {
+    display: flex;
+    justify-content: flex-end;
+
+    .mx_AccessibleButton {
+        margin-inline-start: 18px;
+
+        &.warning {
+            color: $warning-color;
+        }
+    }
+}
diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index 9c939f2fd3..dbc570c872 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -2,7 +2,7 @@
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2017 Vector Creations Ltd.
 Copyright 2017, 2018, 2019 New Vector Ltd
-Copyright 2019 The Matrix.org Foundation C.I.C.
+Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -223,9 +223,10 @@ class _MatrixClientPeg {
         };
 
         opts.cryptoCallbacks = {};
-        if (SettingsStore.isFeatureEnabled("feature_cross_signing")) {
-            Object.assign(opts.cryptoCallbacks, crossSigningCallbacks);
-        }
+        // These are always installed regardless of the labs flag so that
+        // cross-signing features can toggle on without reloading and also be
+        // accessed immediately after login.
+        Object.assign(opts.cryptoCallbacks, crossSigningCallbacks);
 
         this.matrixClient = createMatrixClient(opts);
 
diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
index 628214a2bb..01b9c9c7c8 100644
--- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
+++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js
@@ -313,7 +313,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
             <p>{_t(
                 "Secret Storage will be set up using your existing key backup details. " +
                 "Your secret storage passphrase and recovery key will be the same as " +
-                " they were for your key backup",
+                "they were for your key backup.",
             )}</p>
             <DialogButtons primaryButton={_t('Next')}
                 onPrimaryButtonClick={this._onMigrateNextClick}
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index ed6b7746bc..d9aa5e902d 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -2,7 +2,7 @@
 Copyright 2015, 2016 OpenMarket Ltd
 Copyright 2017 Vector Creations Ltd
 Copyright 2017-2019 New Vector Ltd
-Copyright 2019 The Matrix.org Foundation C.I.C.
+Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import React from 'react';
 import createReactClass from 'create-react-class';
 import PropTypes from 'prop-types';
 import * as Matrix from "matrix-js-sdk";
+import { isCryptoAvailable } from 'matrix-js-sdk/src/crypto';
 
 // focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
 import 'focus-visible';
@@ -79,18 +80,14 @@ export const VIEWS = {
     // we are showing the registration view
     REGISTER: 3,
 
-    // completeing the registration flow
+    // completing the registration flow
     POST_REGISTRATION: 4,
 
     // showing the 'forgot password' view
     FORGOT_PASSWORD: 5,
 
-    // we have valid matrix credentials (either via an explicit login, via the
-    // initial re-animation/guest registration, or via a registration), and are
-    // now setting up a matrixclient to talk to it. This isn't an instant
-    // process because we need to clear out indexeddb. While it is going on we
-    // show a big spinner.
-    LOGGING_IN: 6,
+    // showing flow to trust this new device with cross-signing
+    COMPLETE_SECURITY: 6,
 
     // we are logged in with an active matrix client.
     LOGGED_IN: 7,
@@ -656,16 +653,12 @@ export default createReactClass({
                 });
                 break;
             }
-            case 'on_logging_in':
-                // We are now logging in, so set the state to reflect that
-                // NB. This does not touch 'ready' since if our dispatches
-                // are delayed, the sync could already have completed
-                this.setStateForNewView({
-                    view: VIEWS.LOGGING_IN,
-                });
-                break;
             case 'on_logged_in':
-                if (!Lifecycle.isSoftLogout()) {
+                if (
+                    !Lifecycle.isSoftLogout() &&
+                    this.state.view !== VIEWS.LOGIN &&
+                    this.state.view !== VIEWS.COMPLETE_SECURITY
+                ) {
                     this._onLoggedIn();
                 }
                 break;
@@ -1169,7 +1162,7 @@ export default createReactClass({
             if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) {
                 const welcomeUserRoom = await this._startWelcomeUserChat();
                 if (welcomeUserRoom === null) {
-                    // We didn't rediret to the welcome user room, so show
+                    // We didn't redirect to the welcome user room, so show
                     // the homepage.
                     dis.dispatch({action: 'view_home_page'});
                 }
@@ -1573,6 +1566,10 @@ export default createReactClass({
             dis.dispatch({
                 action: 'view_my_groups',
             });
+        } else if (screen == 'complete_security') {
+            dis.dispatch({
+                action: 'start_complete_security',
+            });
         } else if (screen == 'post_registration') {
             dis.dispatch({
                 action: 'start_post_registration',
@@ -1822,21 +1819,68 @@ export default createReactClass({
         this._loggedInView = ref;
     },
 
+    async onUserCompletedLoginFlow(credentials) {
+        // Create and start the client in the background
+        Lifecycle.setLoggedIn(credentials);
+
+        // Wait for the client to be logged in (but not started)
+        // which is enough to ask the server about account data.
+        await new Promise(resolve => {
+            const actionHandlerRef = dis.register(payload => {
+                if (payload.action !== "on_logged_in") {
+                    return;
+                }
+                dis.unregister(actionHandlerRef);
+                resolve();
+            });
+        });
+
+        const cli = MatrixClientPeg.get();
+        // We're checking `isCryptoAvailable` here instead of `isCryptoEnabled`
+        // because the client hasn't been started yet.
+        if (!isCryptoAvailable()) {
+            this._onLoggedIn();
+        }
+
+        // Test for the master cross-signing key in SSSS as a quick proxy for
+        // whether cross-signing has been set up on the account.
+        let masterKeyInStorage = false;
+        try {
+            masterKeyInStorage = !!await cli.getAccountDataFromServer("m.cross_signing.master");
+        } catch (e) {
+            if (e.errcode !== "M_NOT_FOUND") throw e;
+        }
+
+        if (masterKeyInStorage) {
+            this.setStateForNewView({ view: VIEWS.COMPLETE_SECURITY });
+        } else {
+            this._onLoggedIn();
+        }
+    },
+
+    onCompleteSecurityFinished() {
+        this._onLoggedIn();
+    },
+
     render: function() {
         // console.log(`Rendering MatrixChat with view ${this.state.view}`);
 
         let view;
 
-        if (
-            this.state.view === VIEWS.LOADING ||
-            this.state.view === VIEWS.LOGGING_IN
-        ) {
+        if (this.state.view === VIEWS.LOADING) {
             const Spinner = sdk.getComponent('elements.Spinner');
             view = (
                 <div className="mx_MatrixChat_splash">
                     <Spinner />
                 </div>
             );
+        } else if (this.state.view === VIEWS.COMPLETE_SECURITY) {
+            const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity');
+            view = (
+                <CompleteSecurity
+                    onFinished={this.onCompleteSecurityFinished}
+                />
+            );
         } else if (this.state.view === VIEWS.POST_REGISTRATION) {
             // needs to be before normal PageTypes as you are logged in technically
             const PostRegistration = sdk.getComponent('structures.auth.PostRegistration');
@@ -1921,7 +1965,7 @@ export default createReactClass({
             const Login = sdk.getComponent('structures.auth.Login');
             view = (
                 <Login
-                    onLoggedIn={Lifecycle.setLoggedIn}
+                    onLoggedIn={this.onUserCompletedLoginFlow}
                     onRegisterClick={this.onRegisterClick}
                     fallbackHsUrl={this.getFallbackHsUrl()}
                     defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js
new file mode 100644
index 0000000000..0bc41a8fbb
--- /dev/null
+++ b/src/components/structures/auth/CompleteSecurity.js
@@ -0,0 +1,173 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import { _t } from '../../../languageHandler';
+import sdk from '../../../index';
+import { MatrixClientPeg } from '../../../MatrixClientPeg';
+import { accessSecretStorage } from '../../../CrossSigningManager';
+
+const PHASE_INTRO = 0;
+const PHASE_DONE = 1;
+const PHASE_CONFIRM_SKIP = 2;
+
+export default class CompleteSecurity extends React.Component {
+    static propTypes = {
+        onFinished: PropTypes.func.isRequired,
+    };
+
+    constructor() {
+        super();
+
+        this.state = {
+            phase: PHASE_INTRO,
+        };
+    }
+
+    onStartClick = async () => {
+        const cli = MatrixClientPeg.get();
+        await accessSecretStorage(async () => {
+            await cli.checkOwnCrossSigningTrust();
+        });
+        this.setState({
+            phase: PHASE_DONE,
+        });
+    }
+
+    onSkipClick = () => {
+        this.setState({
+            phase: PHASE_CONFIRM_SKIP,
+        });
+    }
+
+    onSkipConfirmClick = () => {
+        this.props.onFinished();
+    }
+
+    onSkipBackClick = () => {
+        this.setState({
+            phase: PHASE_INTRO,
+        });
+    }
+
+    onDoneClick = () => {
+        this.props.onFinished();
+    }
+
+    render() {
+        const AuthPage = sdk.getComponent("auth.AuthPage");
+        const AuthHeader = sdk.getComponent("auth.AuthHeader");
+        const AuthBody = sdk.getComponent("auth.AuthBody");
+        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
+
+        const {
+            phase,
+        } = this.state;
+
+        let icon;
+        let title;
+        let body;
+        if (phase === PHASE_INTRO) {
+            icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning"></span>;
+            title = _t("Complete security");
+            body = (
+                <div>
+                    <p>{_t(
+                        "Verify this session to grant it access to encrypted messages.",
+                    )}</p>
+                    <div className="mx_CompleteSecurity_actionRow">
+                        <AccessibleButton
+                            kind="danger"
+                            onClick={this.onSkipClick}
+                        >
+                            {_t("Skip")}
+                        </AccessibleButton>
+                        <AccessibleButton
+                            kind="primary"
+                            onClick={this.onStartClick}
+                        >
+                            {_t("Start")}
+                        </AccessibleButton>
+                    </div>
+                </div>
+            );
+        } else if (phase === PHASE_DONE) {
+            icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_verified"></span>;
+            title = _t("Session verified");
+            body = (
+                <div>
+                    <div className="mx_CompleteSecurity_heroIcon mx_E2EIcon_verified"></div>
+                    <p>{_t(
+                        "Your new session is now verified. It has access to your " +
+                        "encrypted messages, and other users will see it as trusted.",
+                    )}</p>
+                    <div className="mx_CompleteSecurity_actionRow">
+                        <AccessibleButton
+                            kind="primary"
+                            onClick={this.onDoneClick}
+                        >
+                            {_t("Done")}
+                        </AccessibleButton>
+                    </div>
+                </div>
+            );
+        } else if (phase === PHASE_CONFIRM_SKIP) {
+            icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning"></span>;
+            title = _t("Are you sure?");
+            body = (
+                <div>
+                    <p>{_t(
+                        "Without completing security on this device, it won’t have " +
+                        "access to encrypted messages.",
+                    )}</p>
+                    <div className="mx_CompleteSecurity_actionRow">
+                        <AccessibleButton
+                            className="warning"
+                            kind="secondary"
+                            onClick={this.onSkipConfirmClick}
+                        >
+                            {_t("Skip")}
+                        </AccessibleButton>
+                        <AccessibleButton
+                            kind="danger"
+                            onClick={this.onSkipBackClick}
+                        >
+                            {_t("Go Back")}
+                        </AccessibleButton>
+                    </div>
+                </div>
+            );
+        } else {
+            throw new Error(`Unknown phase ${phase}`);
+        }
+
+        return (
+            <AuthPage>
+                <AuthHeader />
+                <AuthBody>
+                    <h2 className="mx_CompleteSecurity_header">
+                        {icon}
+                        {title}
+                    </h2>
+                    <div className="mx_CompleteSecurity_body">
+                        {body}
+                    </div>
+                </AuthBody>
+            </AuthPage>
+        );
+    }
+}
diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js
index 63f590da2e..40800ad907 100644
--- a/src/components/structures/auth/SoftLogout.js
+++ b/src/components/structures/auth/SoftLogout.js
@@ -66,7 +66,7 @@ export default class SoftLogout extends React.Component {
     componentDidMount(): void {
         // We've ended up here when we don't need to - navigate to login
         if (!Lifecycle.isSoftLogout()) {
-            dis.dispatch({action: "on_logged_in"});
+            dis.dispatch({action: "start_login"});
             return;
         }
 
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 42c87172b8..3756b4c60b 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1848,6 +1848,14 @@
     "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s",
     "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
     "Could not load user profile": "Could not load user profile",
+    "Complete security": "Complete security",
+    "Verify this session to grant it access to encrypted messages.": "Verify this session to grant it access to encrypted messages.",
+    "Start": "Start",
+    "Session verified": "Session verified",
+    "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.",
+    "Done": "Done",
+    "Without completing security on this device, it won’t have access to encrypted messages.": "Without completing security on this device, it won’t have access to encrypted messages.",
+    "Go Back": "Go Back",
     "Failed to send email": "Failed to send email",
     "The email address linked to your account must be entered.": "The email address linked to your account must be entered.",
     "A new password must be entered.": "A new password must be entered.",
@@ -1952,7 +1960,7 @@
     "Import": "Import",
     "Key Backup is enabled on your account but has not been set up from this session. To set up secret storage, restore your key backup.": "Key Backup is enabled on your account but has not been set up from this session. To set up secret storage, restore your key backup.",
     "Restore": "Restore",
-    "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as  they were for your key backup": "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as  they were for your key backup",
+    "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.": "Secret Storage will be set up using your existing key backup details. Your secret storage passphrase and recovery key will be the same as they were for your key backup.",
     "Great! This passphrase looks strong enough.": "Great! This passphrase looks strong enough.",
     "<b>Warning</b>: You should only set up secret storage from a trusted computer.": "<b>Warning</b>: You should only set up secret storage from a trusted computer.",
     "We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.": "We'll use secret storage to optionally store an encrypted copy of your cross-signing identity for verifying other devices and message keys on our server. Protect your access to encrypted messages with a passphrase to keep it secure.",
diff --git a/src/settings/Settings.js b/src/settings/Settings.js
index 8ee8d89890..2b8c0aef89 100644
--- a/src/settings/Settings.js
+++ b/src/settings/Settings.js
@@ -1,7 +1,7 @@
 /*
 Copyright 2017 Travis Ralston
 Copyright 2018, 2019 New Vector Ltd.
-Copyright 2019 The Matrix.org Foundation C.I.C.
+Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -153,7 +153,6 @@ export const SETTINGS = {
         displayName: _td("Enable cross-signing to verify per-user instead of per-device (in development)"),
         supportedLevels: LEVELS_FEATURE,
         default: false,
-        controller: new ReloadOnChangeController(),
     },
     "feature_event_indexing": {
         isFeature: true,

From 6e027badc0b0f5e7a32ec340b0aa33033d658896 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Wed, 15 Jan 2020 22:10:59 +0000
Subject: [PATCH 84/86] Tweak comparison

Co-Authored-By: Travis Ralston <travpc@gmail.com>
---
 src/components/structures/MatrixChat.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index d9aa5e902d..edc0501086 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -1566,7 +1566,7 @@ export default createReactClass({
             dis.dispatch({
                 action: 'view_my_groups',
             });
-        } else if (screen == 'complete_security') {
+        } else if (screen === 'complete_security') {
             dis.dispatch({
                 action: 'start_complete_security',
             });

From 71fa3222fef38715584c877c7e499e2f98941ded Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Wed, 15 Jan 2020 22:11:22 +0000
Subject: [PATCH 85/86] Fix component index import

Co-Authored-By: Travis Ralston <travpc@gmail.com>
---
 src/components/structures/auth/CompleteSecurity.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js
index 0bc41a8fbb..77f7fe26e4 100644
--- a/src/components/structures/auth/CompleteSecurity.js
+++ b/src/components/structures/auth/CompleteSecurity.js
@@ -17,7 +17,7 @@ limitations under the License.
 import React from 'react';
 import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
-import sdk from '../../../index';
+import * as sdk from '../../../index';
 import { MatrixClientPeg } from '../../../MatrixClientPeg';
 import { accessSecretStorage } from '../../../CrossSigningManager';
 

From 5926e277c485d7833c6b75b52ccdbfc33db6034e Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 16 Jan 2020 11:52:02 +0000
Subject: [PATCH 86/86] Avoid logged in event race

---
 src/components/structures/MatrixChat.js | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index edc0501086..c59c44ebd8 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -1820,12 +1820,9 @@ export default createReactClass({
     },
 
     async onUserCompletedLoginFlow(credentials) {
-        // Create and start the client in the background
-        Lifecycle.setLoggedIn(credentials);
-
         // Wait for the client to be logged in (but not started)
         // which is enough to ask the server about account data.
-        await new Promise(resolve => {
+        const loggedIn = new Promise(resolve => {
             const actionHandlerRef = dis.register(payload => {
                 if (payload.action !== "on_logged_in") {
                     return;
@@ -1835,6 +1832,10 @@ export default createReactClass({
             });
         });
 
+        // Create and start the client in the background
+        Lifecycle.setLoggedIn(credentials);
+        await loggedIn;
+
         const cli = MatrixClientPeg.get();
         // We're checking `isCryptoAvailable` here instead of `isCryptoEnabled`
         // because the client hasn't been started yet.